def _handle_global_configuration(): # print location of global configuration print(MSG_GLOBAL_SETTINGS_LOCATION.format(GLOBAL_CONFIG_PATH)) # set up the config parsers file_config = get_config_parser() config_exists = file_config.read([GLOBAL_CONFIG_PATH]) global_config = get_config_parser() global_config.read(GLOBAL_CONFIG_PATH) should_modify_global_config = False if config_exists: # print current config and prompt to allow global config modification print(MSG_HEADING_CURRENT_CONFIG_INFO) print_current_configuration(file_config) should_modify_global_config = prompt_y_n(MSG_PROMPT_MANAGE_GLOBAL, default='n') answers['modify_global_prompt'] = should_modify_global_config if not config_exists or should_modify_global_config: # no config exists yet so configure global config or user wants to modify global config output_index = prompt_choice_list(MSG_PROMPT_GLOBAL_OUTPUT, OUTPUT_LIST, default=get_default_from_config( global_config, 'core', 'output', OUTPUT_LIST)) answers['output_type_prompt'] = output_index answers['output_type_options'] = str(OUTPUT_LIST) try: from vsts.cli.code.common.git_alias import setup_git_aliases, are_git_aliases_setup if not are_git_aliases_setup(): setup_aliases = prompt_y_n(MSG_PROMPT_GIT_ALIAS, default='y') if setup_aliases: answers['git_aliases'] = True setup_git_aliases() else: answers['git_aliases'] = False else: answers['git_aliases'] = True except (ModuleNotFoundError, CLIError): logging.debug( 'Skipping git alias configuration, because module was not found.' ) enable_file_logging = prompt_y_n(MSG_PROMPT_FILE_LOGGING, default='n') allow_telemetry = prompt_y_n(MSG_PROMPT_TELEMETRY, default='y') answers['telemetry_prompt'] = allow_telemetry # save the global config try: global_config.add_section('core') except configparser.DuplicateSectionError: pass try: global_config.add_section('logging') except configparser.DuplicateSectionError: pass global_config.set('core', 'output', OUTPUT_LIST[output_index]['name']) global_config.set('core', 'collect_telemetry', 'yes' if allow_telemetry else 'no') global_config.set('logging', 'enable_log_file', 'yes' if enable_file_logging else 'no') set_global_config(global_config)
def test_get_clouds_concurrent(self): with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as config_file: pool_size = 100 p = multiprocessing.Pool(pool_size) p.map(_helper_get_clouds, range(pool_size)) p.close() p.join() # Check we can read the file with no exceptions cli = DummyCli() get_config_parser().read(config_file) for kc in KNOWN_CLOUDS: get_cloud(cli, kc.name)
def __init__(self, config_dir=AZ_DEVOPS_GLOBAL_CONFIG_DIR, config_env_var_prefix=CLI_ENV_VARIABLE_PREFIX): super(AzDevopsConfig, self).__init__(config_dir=config_dir, config_env_var_prefix=config_env_var_prefix) self.config_parser = get_config_parser()
def get_cloud_subscription(cloud_name): config = get_config_parser() config.read(CLOUD_CONFIG_FILE) try: return config.get(cloud_name, 'subscription') except (configparser.NoOptionError, configparser.NoSectionError): return None
def get_clouds(cli_ctx): clouds = [] config = get_config_parser() # Start off with known clouds and apply config file on top of current config for c in KNOWN_CLOUDS: _config_add_cloud(config, c) config.read(CLOUD_CONFIG_FILE) for section in config.sections(): c = Cloud(section) for option in config.options(section): if option == 'profile': c.profile = config.get(section, option) if option.startswith('endpoint_'): setattr(c.endpoints, option.replace('endpoint_', ''), config.get(section, option)) elif option.startswith('suffix_'): setattr(c.suffixes, option.replace('suffix_', ''), config.get(section, option)) if c.profile is None: # If profile isn't set, use latest setattr(c, 'profile', 'latest') if c.profile not in API_PROFILES: raise CLIError('Profile {} does not exist or is not supported.'.format(c.profile)) if not c.endpoints.has_endpoint_set('management') and \ c.endpoints.has_endpoint_set('resource_manager'): # If management endpoint not set, use resource manager endpoint c.endpoints.management = c.endpoints.resource_manager clouds.append(c) active_cloud_name = get_active_cloud_name(cli_ctx) for c in clouds: if c.name == active_cloud_name: c.is_active = True break return clouds
def get_cloud_subscription(cloud_name): config = get_config_parser() config.read(CLOUD_CONFIG_FILE) try: return config.get(cloud_name, 'subscription') except (configparser.NoOptionError, configparser.NoSectionError): return None
def test_set_config_value_duplicate_section_ok(self): self.cli_config.set_value('test_section', 'test_option', 'a_value') self.cli_config.set_value('test_section', 'test_option_another', 'another_value') config = get_config_parser() config.read(self.cli_config.config_path) self.assertEqual(config.get('test_section', 'test_option'), 'a_value') self.assertEqual(config.get('test_section', 'test_option_another'), 'another_value')
def get_clouds(cli_ctx): clouds = [] config = get_config_parser() # Start off with known clouds and apply config file on top of current config for c in KNOWN_CLOUDS: _config_add_cloud(config, c) config.read(CLOUD_CONFIG_FILE) for section in config.sections(): c = Cloud(section) for option in config.options(section): if option == 'profile': c.profile = config.get(section, option) if option.startswith('endpoint_'): setattr(c.endpoints, option.replace('endpoint_', ''), config.get(section, option)) elif option.startswith('suffix_'): setattr(c.suffixes, option.replace('suffix_', ''), config.get(section, option)) if c.profile is None: # If profile isn't set, use latest setattr(c, 'profile', 'latest') if c.profile not in API_PROFILES: raise CLIError('Profile {} does not exist or is not supported.'.format(c.profile)) if not c.endpoints.has_endpoint_set('management') and \ c.endpoints.has_endpoint_set('resource_manager'): # If management endpoint not set, use resource manager endpoint c.endpoints.management = c.endpoints.resource_manager clouds.append(c) active_cloud_name = get_active_cloud_name(cli_ctx) for c in clouds: if c.name == active_cloud_name: c.is_active = True break return clouds
def _save_cloud(cloud, overwrite=False): config = get_config_parser() config.read(CLOUD_CONFIG_FILE) _config_add_cloud(config, cloud, overwrite=overwrite) if not os.path.isdir(GLOBAL_CONFIG_DIR): os.makedirs(GLOBAL_CONFIG_DIR) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def test_get_clouds_concurrent(self): with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as config_file: # Max pool_size is 61, otherwise exception will be thrown on Python 3.8 Windows: # File "...Python38\lib\multiprocessing\connection.py", line 810, in _exhaustive_wait # res = _winapi.WaitForMultipleObjects(L, False, timeout) # ValueError: need at most 63 handles, got a sequence of length 102 pool_size = 20 p = multiprocessing.Pool(pool_size) p.map(_helper_get_clouds, range(pool_size)) p.close() p.join() # Check we can read the file with no exceptions cli = DummyCli() get_config_parser().read(config_file) for kc in KNOWN_CLOUDS: get_cloud(cli, kc.name)
def _save_cloud(cloud, overwrite=False): config = get_config_parser() config.read(CLOUD_CONFIG_FILE) _config_add_cloud(config, cloud, overwrite=overwrite) if not os.path.isdir(GLOBAL_CONFIG_DIR): os.makedirs(GLOBAL_CONFIG_DIR) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def set_global_config_value(section, option, value): config = get_config_parser() config.read(GLOBAL_CONFIG_PATH) try: config.add_section(section) except configparser.DuplicateSectionError: pass config.set(section, option, _normalize_config_value(value)) set_global_config(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 file_config = get_config_parser() config_exists = file_config.read([config.config_path]) should_modify_global_config = False if config_exists: # print current config and prompt to allow global config modification _print_cur_configuration(file_config) should_modify_global_config = prompt_y_n(MSG_PROMPT_MANAGE_GLOBAL, default='n') answers['modify_global_prompt'] = should_modify_global_config if not config_exists or should_modify_global_config: # no config exists yet so configure global config or user wants to modify global config with ConfiguredDefaultSetter(config, False): output_index = prompt_choice_list(MSG_PROMPT_GLOBAL_OUTPUT, OUTPUT_LIST, default=get_default_from_config( config, 'core', 'output', OUTPUT_LIST)) 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') 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: try: cache_ttl = prompt( MSG_PROMPT_CACHE_TTL) or DEFAULT_CACHE_TTL # ensure valid int by casting cache_value = int(cache_ttl) if cache_value < 1: raise ValueError except ValueError: logger.error('TTL must be a positive integer') cache_ttl = None # save the global config config.set_value('core', 'output', OUTPUT_LIST[output_index]['name']) config.set_value('core', 'collect_telemetry', 'yes' if allow_telemetry else 'no') config.set_value('core', 'cache_ttl', cache_ttl) config.set_value('logging', 'enable_log_file', 'yes' if enable_file_logging else 'no')
def test_add_get_cloud_with_invalid_profile(self): # Cloud has profile that doesn't exist so an exception should be raised cli = DummyCli() profile = 'none-existent-profile' c = Cloud('MyOwnCloud', profile=profile) with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as\ config_file: add_cloud(cli, c) config = get_config_parser() config.read(config_file) self.assertTrue(c.name in config.sections()) self.assertEqual(config.get(c.name, 'profile'), profile) with self.assertRaises(CLIError): get_custom_clouds(cli)
def remove_cloud(cli_ctx, cloud_name): if not _get_cloud(cli_ctx, cloud_name): raise CloudNotRegisteredException(cloud_name) if cloud_name == cli_ctx.cloud.name: raise CannotUnregisterCloudException("The cloud '{}' cannot be unregistered " "as it's currently active.".format(cloud_name)) is_known_cloud = next((x for x in KNOWN_CLOUDS if x.name == cloud_name), None) if is_known_cloud: raise CannotUnregisterCloudException("The cloud '{}' cannot be unregistered " "as it's not a custom cloud.".format(cloud_name)) config = get_config_parser() config.read(CLOUD_CONFIG_FILE) config.remove_section(cloud_name) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def remove_cloud(cli_ctx, cloud_name): if not _get_cloud(cli_ctx, cloud_name): raise CloudNotRegisteredException(cloud_name) if cloud_name == cli_ctx.cloud.name: raise CannotUnregisterCloudException("The cloud '{}' cannot be unregistered " "as it's currently active.".format(cloud_name)) is_known_cloud = next((x for x in KNOWN_CLOUDS if x.name == cloud_name), None) if is_known_cloud: raise CannotUnregisterCloudException("The cloud '{}' cannot be unregistered " "as it's not a custom cloud.".format(cloud_name)) config = get_config_parser() config.read(CLOUD_CONFIG_FILE) config.remove_section(cloud_name) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def print_current_configuration(file_config=None): if file_config is None: file_config = get_config_parser() file_config.read([GLOBAL_CONFIG_PATH]) for section in file_config.sections(): print() print('[{}]'.format(section)) for option in file_config.options(section): print('{} = {}'.format(option, file_config.get(section, option))) env_vars = [ ev for ev in os.environ if ev.startswith(CLI_ENV_VARIABLE_PREFIX) ] if env_vars: print(MSG_HEADING_ENV_VARS) print('\n'.join( ['{} = {}'.format(ev, os.environ[ev]) for ev in env_vars]))
def set_cloud_subscription(cli_ctx, cloud_name, subscription): if not _get_cloud(cli_ctx, cloud_name): raise CloudNotRegisteredException(cloud_name) config = get_config_parser() config.read(CLOUD_CONFIG_FILE) if subscription: try: config.add_section(cloud_name) except configparser.DuplicateSectionError: pass config.set(cloud_name, 'subscription', subscription) else: try: config.remove_option(cloud_name, 'subscription') except configparser.NoSectionError: pass if not os.path.isdir(GLOBAL_CONFIG_DIR): os.makedirs(GLOBAL_CONFIG_DIR) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def set_cloud_subscription(cli_ctx, cloud_name, subscription): if not _get_cloud(cli_ctx, cloud_name): raise CloudNotRegisteredException(cloud_name) config = get_config_parser() config.read(CLOUD_CONFIG_FILE) if subscription: try: config.add_section(cloud_name) except configparser.DuplicateSectionError: pass config.set(cloud_name, 'subscription', subscription) else: try: config.remove_option(cloud_name, 'subscription') except configparser.NoSectionError: pass if not os.path.isdir(GLOBAL_CONFIG_DIR): os.makedirs(GLOBAL_CONFIG_DIR) with open(CLOUD_CONFIG_FILE, 'w') as configfile: config.write(configfile)
def test_add_get_delete_custom_cloud(self): cli = DummyCli() endpoint_rm = 'http://management.contoso.com' suffix_storage = 'core.contoso.com' suffix_acr_login_server = '.azurecr-test.io' endpoints = CloudEndpoints(resource_manager=endpoint_rm) suffixes = CloudSuffixes( storage_endpoint=suffix_storage, acr_login_server_endpoint=suffix_acr_login_server) c = Cloud('MyOwnCloud', endpoints=endpoints, suffixes=suffixes) with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as\ config_file: with mock.patch('azure.cli.core.cloud.get_custom_clouds', lambda: []): add_cloud(cli, c) config = get_config_parser() config.read(config_file) self.assertTrue(c.name in config.sections()) self.assertEqual( config.get(c.name, 'endpoint_resource_manager'), endpoint_rm) self.assertEqual(config.get(c.name, 'suffix_storage_endpoint'), suffix_storage) self.assertEqual( config.get(c.name, 'suffix_acr_login_server_endpoint'), suffix_acr_login_server) custom_clouds = get_custom_clouds(cli) self.assertEqual(len(custom_clouds), 1) self.assertEqual(custom_clouds[0].name, c.name) self.assertEqual(custom_clouds[0].endpoints.resource_manager, c.endpoints.resource_manager) self.assertEqual(custom_clouds[0].suffixes.storage_endpoint, c.suffixes.storage_endpoint) self.assertEqual( custom_clouds[0].suffixes.acr_login_server_endpoint, c.suffixes.acr_login_server_endpoint) with mock.patch('azure.cli.core.cloud._get_cloud', lambda _, _1: c): remove_cloud(cli, c.name) custom_clouds = get_custom_clouds(cli) self.assertEqual(len(custom_clouds), 0)
def test_add_get_cloud_with_profile(self): cli = DummyCli() endpoint_rm = 'http://management.contoso.com' endpoints = CloudEndpoints(resource_manager=endpoint_rm) profile = '2017-03-09-profile' c = Cloud('MyOwnCloud', endpoints=endpoints, profile=profile) with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as\ config_file: add_cloud(cli, c) config = get_config_parser() config.read(config_file) self.assertTrue(c.name in config.sections()) self.assertEqual(config.get(c.name, 'endpoint_resource_manager'), endpoint_rm) self.assertEqual(config.get(c.name, 'profile'), profile) custom_clouds = get_custom_clouds(cli) self.assertEqual(len(custom_clouds), 1) self.assertEqual(custom_clouds[0].name, c.name) self.assertEqual(custom_clouds[0].endpoints.resource_manager, c.endpoints.resource_manager) self.assertEqual(custom_clouds[0].profile, c.profile)
def test_modify_known_cloud(self): with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]) as config_file: cli = DummyCli() config = get_config_parser() cloud_name = AZURE_PUBLIC_CLOUD.name cloud = get_cloud(cli, cloud_name) self.assertEqual(cloud.name, cloud_name) mcloud = Cloud(cloud_name) mcloud.endpoints.gallery = 'https://mynewcustomgallery.azure.com' update_cloud(cli, mcloud) cloud = get_cloud(cli, cloud_name) self.assertEqual(cloud.endpoints.gallery, 'https://mynewcustomgallery.azure.com') # Check that the config file only has what we changed, not the full cloud info. config.read(config_file) items = config.items(cloud_name) self.assertEqual(len(items), 1) self.assertEqual( items[0], ('endpoint_gallery', 'https://mynewcustomgallery.azure.com'))
def print_current_configuration(file_config=None): from azext_devops.dev.repos.git_alias import are_git_aliases_setup if file_config is None: file_config = get_config_parser() file_config.read([AZ_DEVOPS_GLOBAL_CONFIG_PATH]) for section in file_config.sections(): print() print('[{}]'.format(section)) for option in file_config.options(section): print('{} = {}'.format(option, file_config.get(section, option))) # Print if git alias is setup or not is_git_alias_setup = MSG_NO if are_git_aliases_setup(): is_git_alias_setup = MSG_YES print('{} = {}'.format(MSG_GIT_ALIAS_SETUP, is_git_alias_setup)) env_vars = [ ev for ev in os.environ if ev.startswith(CLI_ENV_VARIABLE_PREFIX) ] if env_vars: print(MSG_HEADING_ENV_VARS) print('\n'.join(['{}'.format(ev) for ev in env_vars]))
def test_set_config_value(self): self.cli_config.set_value('test_section', 'test_option', 'a_value') config = get_config_parser() config.read(self.cli_config.config_path) self.assertEqual(config.get('test_section', 'test_option'), 'a_value')