diff --git a/src/azure-cli-core/azure/cli/core/cloud.py b/src/azure-cli-core/azure/cli/core/cloud.py index 6ad6990a3e0..71ae39adb66 100644 --- a/src/azure-cli-core/azure/cli/core/cloud.py +++ b/src/azure-cli-core/azure/cli/core/cloud.py @@ -18,8 +18,14 @@ logger = get_logger(__name__) +# This default cloud name. If you use DummyCli(random_config_dir=True), use get_cloud_config_file() instead. CLOUD_CONFIG_FILE = os.path.join(GLOBAL_CONFIG_DIR, 'clouds.config') + +def get_cloud_config_file(cli_ctx=None): + return os.path.join(cli_ctx.config.config_dir, 'clouds.config') if cli_ctx else CLOUD_CONFIG_FILE + + # Add names of clouds that don't allow telemetry data collection here such as some air-gapped clouds. CLOUDS_FORBIDDING_TELEMETRY = ['USSec', 'USNat'] @@ -511,10 +517,10 @@ def get_clouds(cli_ctx): for c in KNOWN_CLOUDS: _config_add_cloud(config, c) try: - config.read(CLOUD_CONFIG_FILE) + config.read(get_cloud_config_file(cli_ctx)) except configparser.MissingSectionHeaderError: - os.remove(CLOUD_CONFIG_FILE) - logger.warning("'%s' is in bad format and has been removed.", CLOUD_CONFIG_FILE) + os.remove(get_cloud_config_file(cli_ctx)) + logger.warning("'%s' is in bad format and has been removed.", get_cloud_config_file(cli_ctx)) for section in config.sections(): c = Cloud(section) for option in config.options(section): @@ -563,9 +569,9 @@ def get_active_cloud(cli_ctx=None): return get_cloud(cli_ctx, default_cloud_name) -def get_cloud_subscription(cloud_name): +def get_cloud_subscription(cloud_name, cli_ctx=None): config = configparser.ConfigParser() - config.read(CLOUD_CONFIG_FILE) + config.read(get_cloud_config_file(cli_ctx)) try: return config.get(cloud_name, 'subscription') except (configparser.NoOptionError, configparser.NoSectionError): @@ -576,7 +582,7 @@ def set_cloud_subscription(cli_ctx, cloud_name, subscription): if not _get_cloud(cli_ctx, cloud_name): raise CloudNotRegisteredException(cloud_name) config = configparser.ConfigParser() - config.read(CLOUD_CONFIG_FILE) + config.read(get_cloud_config_file(cli_ctx)) if subscription: try: config.add_section(cloud_name) @@ -588,9 +594,9 @@ def set_cloud_subscription(cli_ctx, cloud_name, subscription): 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: + if not os.path.isdir(os.path.dirname(get_cloud_config_file(cli_ctx))): + os.makedirs(os.path.dirname(get_cloud_config_file(cli_ctx))) + with open(get_cloud_config_file(cli_ctx), 'w') as configfile: config.write(configfile) @@ -598,7 +604,7 @@ def _set_active_subscription(cli_ctx, cloud_name): from azure.cli.core._profile import (Profile, _ENVIRONMENT_NAME, _SUBSCRIPTION_ID, _STATE, _SUBSCRIPTION_NAME) profile = Profile(cli_ctx=cli_ctx) - subscription_to_use = get_cloud_subscription(cloud_name) or \ + subscription_to_use = get_cloud_subscription(cloud_name, cli_ctx) or \ next((s[_SUBSCRIPTION_ID] for s in profile.load_cached_subscriptions() # noqa if s[_STATE] == 'Enabled'), None) @@ -644,26 +650,26 @@ def _config_add_cloud(config, cloud, overwrite=False): config.set(cloud.name, 'suffix_{}'.format(k), v) -def _save_cloud(cloud, overwrite=False): +def _save_cloud(cloud, overwrite=False, cli_ctx=None): config = configparser.ConfigParser() - config.read(CLOUD_CONFIG_FILE) + config.read(get_cloud_config_file(cli_ctx)) _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: + if not os.path.isdir(os.path.dirname(get_cloud_config_file(cli_ctx))): + os.makedirs(os.path.dirname(get_cloud_config_file(cli_ctx))) + with open(get_cloud_config_file(cli_ctx), 'w') as configfile: config.write(configfile) def add_cloud(cli_ctx, cloud): if _get_cloud(cli_ctx, cloud.name): raise CloudAlreadyRegisteredException(cloud.name) - _save_cloud(cloud) + _save_cloud(cloud, cli_ctx=cli_ctx) def update_cloud(cli_ctx, cloud): if not _get_cloud(cli_ctx, cloud.name): raise CloudNotRegisteredException(cloud.name) - _save_cloud(cloud, overwrite=True) + _save_cloud(cloud, overwrite=True, cli_ctx=cli_ctx) def remove_cloud(cli_ctx, cloud_name): @@ -677,9 +683,9 @@ def remove_cloud(cli_ctx, cloud_name): raise CannotUnregisterCloudException("The cloud '{}' cannot be unregistered " "as it's not a custom cloud.".format(cloud_name)) config = configparser.ConfigParser() - config.read(CLOUD_CONFIG_FILE) + config.read(get_cloud_config_file(cli_ctx)) config.remove_section(cloud_name) - with open(CLOUD_CONFIG_FILE, 'w') as configfile: + with open(get_cloud_config_file(cli_ctx), 'w') as configfile: config.write(configfile) diff --git a/src/azure-cli-core/azure/cli/core/tests/test_cloud.py b/src/azure-cli-core/azure/cli/core/tests/test_cloud.py index e184e26b79f..1ddfbe7e935 100644 --- a/src/azure-cli-core/azure/cli/core/tests/test_cloud.py +++ b/src/azure-cli-core/azure/cli/core/tests/test_cloud.py @@ -27,7 +27,8 @@ CannotUnregisterCloudException, switch_active_cloud, get_known_clouds, - HARD_CODED_CLOUD_LIST) + HARD_CODED_CLOUD_LIST, + get_cloud_config_file) from azure.cli.core._profile import Profile @@ -38,21 +39,21 @@ def _helper_get_clouds(_): """ Helper method for multiprocessing.Pool.map func that uses throwaway arg """ - get_clouds(DummyCli()) + get_clouds(DummyCli(random_config_dir=True)) class TestCloud(unittest.TestCase): def test_endpoint_none(self): with self.assertRaises(CloudEndpointNotSetException): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) cli.cloud = Cloud('AzureCloud') profile = Profile(cli_ctx=cli) profile.get_login_credentials() @mock.patch('azure.cli.core.cloud.get_custom_clouds', lambda: []) def test_add_get_delete_custom_cloud(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) endpoint_rm = 'http://management.contoso.com' suffix_storage = 'core.contoso.com' suffix_acr_login_server = '.azurecr-test.io' @@ -60,95 +61,90 @@ def test_add_get_delete_custom_cloud(self): 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 = configparser.ConfigParser() - 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) + with mock.patch('azure.cli.core.cloud.get_custom_clouds', lambda: []): + add_cloud(cli, c) + config_file = get_cloud_config_file(cli) + config = configparser.ConfigParser() + 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() + cli = DummyCli(random_config_dir=True) 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 = configparser.ConfigParser() - 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) + add_cloud(cli, c) + config_file = get_cloud_config_file(cli) + config = configparser.ConfigParser() + 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_add_get_cloud_with_hybrid_profile(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) endpoint_rm = 'http://management.contoso.com' endpoints = CloudEndpoints(resource_manager=endpoint_rm) profile = '2018-03-01-hybrid' 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 = configparser.ConfigParser() - 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) + add_cloud(cli, c) + config_file = get_cloud_config_file(cli) + config = configparser.ConfigParser() + 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_add_get_cloud_with_invalid_profile(self): # Cloud has profile that doesn't exist so an exception should be raised - cli = DummyCli() + cli = DummyCli(random_config_dir=True) 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 = configparser.ConfigParser() - 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) + add_cloud(cli, c) + config_file = get_cloud_config_file(cli) + config = configparser.ConfigParser() + 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 test_get_default_latest_profile(self): - with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]): - cli = DummyCli() - clouds = get_clouds(cli) - for c in clouds: - self.assertEqual(c.profile, 'latest') + cli = DummyCli(random_config_dir=True) + clouds = get_clouds(cli) + for c in clouds: + self.assertEqual(c.profile, 'latest') def test_custom_cloud_management_endpoint_set(self): # We have set management endpoint so don't override it - cli = DummyCli() + cli = DummyCli(random_config_dir=True) endpoint_rm = 'http://management.contoso.com' endpoint_mgmt = 'http://management.core.contoso.com' endpoints = CloudEndpoints(resource_manager=endpoint_rm, management=endpoint_mgmt) @@ -166,7 +162,7 @@ def test_custom_cloud_management_endpoint_set(self): def test_custom_cloud_no_management_endpoint_set(self): # Use ARM 'resource manager' endpoint as 'management' (old ASM) endpoint if only ARM endpoint is set - cli = DummyCli() + cli = DummyCli(random_config_dir=True) endpoint_rm = 'http://management.contoso.com' endpoints = CloudEndpoints(resource_manager=endpoint_rm) profile = '2017-03-09-profile' @@ -182,61 +178,61 @@ def test_custom_cloud_no_management_endpoint_set(self): c.endpoints.resource_manager) def test_get_active_cloud_name_default(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) expected = AZURE_PUBLIC_CLOUD.name actual = get_active_cloud_name(cli) self.assertEqual(expected, actual) def test_get_known_clouds(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]): # Check that we can get all the known clouds without any exceptions for kc in KNOWN_CLOUDS: get_cloud(cli, kc.name) 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 = configparser.ConfigParser() - 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')) + cli = DummyCli(random_config_dir=True) + config_file = get_cloud_config_file(cli) + config = configparser.ConfigParser() + 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 test_remove_known_cloud(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) with mock.patch('azure.cli.core.cloud.CLOUD_CONFIG_FILE', tempfile.mkstemp()[1]): with self.assertRaises(CannotUnregisterCloudException): remove_cloud(cli, AZURE_PUBLIC_CLOUD.name) 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() - configparser.ConfigParser().read(config_file) - for kc in KNOWN_CLOUDS: - get_cloud(cli, kc.name) + # 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(random_config_dir=True) + config_file = get_cloud_config_file(cli) + configparser.ConfigParser().read(config_file) + for kc in KNOWN_CLOUDS: + get_cloud(cli, kc.name) def test_cloud_is_registered(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) self.assertTrue(cloud_is_registered(cli, AZURE_PUBLIC_CLOUD.name)) self.assertFalse(cloud_is_registered(cli, 'MyUnknownCloud')) diff --git a/src/azure-cli-core/azure/cli/core/tests/test_profile.py b/src/azure-cli-core/azure/cli/core/tests/test_profile.py index a5c32141b7c..087e361693d 100644 --- a/src/azure-cli-core/azure/cli/core/tests/test_profile.py +++ b/src/azure-cli-core/azure/cli/core/tests/test_profile.py @@ -282,7 +282,7 @@ def test_login_with_auth_code(self, can_launch_browser_mock, login_with_auth_cod create_subscription_client_mock): login_with_auth_code_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -304,7 +304,7 @@ def test_login_with_device_code(self, login_with_device_code_mock, get_user_cred create_subscription_client_mock): login_with_device_code_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -324,7 +324,7 @@ def test_login_with_device_code_for_tenant(self, login_with_device_code_mock, ge create_subscription_client_mock): login_with_device_code_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -345,7 +345,7 @@ def test_login_with_username_password_for_tenant(self, login_with_username_passw create_subscription_client_mock): login_with_username_password_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -364,7 +364,7 @@ def test_login_with_username_password_for_tenant(self, login_with_username_passw def test_login_with_service_principal(self, login_with_service_principal_mock, get_service_principal_credential_mock, create_subscription_client_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -396,7 +396,7 @@ def test_login_with_service_principal(self, login_with_service_principal_mock, def test_login_in_cloud_shell(self, msi_auth_mock, create_subscription_client_mock): msi_auth_mock.return_value = MSRestAzureAuthStub() - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] @@ -425,7 +425,7 @@ def test_find_subscriptions_in_vm_with_msi_system_assigned(self, create_subscrip mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] create_subscription_client_mock.return_value = mock_subscription_client - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -458,7 +458,7 @@ def test_find_subscriptions_in_vm_with_msi_no_subscriptions(self, create_subscri mock_subscription_client.subscriptions.list.return_value = [] create_subscription_client_mock.return_value = mock_subscription_client - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -493,7 +493,7 @@ def test_find_subscriptions_in_vm_with_msi_user_assigned_with_client_id(self, cr mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] create_subscription_client_mock.return_value = mock_subscription_client - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -548,7 +548,7 @@ def set_token(self): raise AzureResponseError('Failed to connect to MSI. Please make sure MSI is configured correctly.\n' 'Get Token request returned http error: 400, reason: Bad Request') - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) mock_msi_auth.side_effect = AuthStub test_object_id = '54826b22-38d6-4fb2-bad9-b7b93a3e9999' @@ -569,7 +569,7 @@ def test_find_subscriptions_in_vm_with_msi_user_assigned_with_res_id(self, creat mock_subscription_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] create_subscription_client_mock.return_value = mock_subscription_client - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -602,7 +602,7 @@ def test_login_no_subscription(self, can_launch_browser_mock, create_subscription_client_mock): login_with_auth_code_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [TenantStub(self.tenant_id)] mock_subscription_client.subscriptions.list.return_value = [] @@ -628,7 +628,7 @@ def test_login_no_tenant(self, can_launch_browser_mock, create_subscription_client_mock): login_with_auth_code_mock.return_value = self.user_identity_mock - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_subscription_client = mock.MagicMock() mock_subscription_client.tenants.list.return_value = [] mock_subscription_client.subscriptions.list.return_value = [] @@ -647,7 +647,7 @@ def test_login_no_tenant(self, can_launch_browser_mock, def test_login_with_auth_code_adfs(self, can_launch_browser_mock, login_with_auth_code_mock, get_user_credential_mock, create_subscription_client_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) TEST_ADFS_AUTH_URL = 'https://adfs.local.azurestack.external/adfs' def login_with_auth_code_mock_side_effect(identity_self, *args, **kwargs): @@ -675,7 +675,7 @@ def login_with_auth_code_mock_side_effect(identity_self, *args, **kwargs): self.assertEqual(self.subscription1_output, subs) def test_normalize(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) consolidated = profile._normalize_properties(self.user1, [self.subscription1], False) @@ -685,7 +685,7 @@ def test_normalize(self): self.assertIsNotNone(json.dumps(consolidated[0])) def test_normalize_v2016_06_01(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) from azure.mgmt.resource.subscriptions.v2016_06_01.models import Subscription \ @@ -716,7 +716,7 @@ def test_normalize_v2016_06_01(self): self.assertIsNotNone(json.dumps(consolidated[0])) def test_update_add_two_different_subscriptions(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -750,7 +750,7 @@ def test_update_add_two_different_subscriptions(self): self.assertFalse(storage_mock['subscriptions'][0]['isDefault']) def test_update_with_same_subscription_added_twice(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -773,7 +773,7 @@ def test_update_with_same_subscription_added_twice(self): self.assertTrue(storage_mock['subscriptions'][0]['isDefault']) def test_set_active_subscription(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -794,7 +794,7 @@ def test_set_active_subscription(self): self.assertTrue(storage_mock['subscriptions'][0]['isDefault']) def test_default_active_subscription_to_non_disabled_one(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -808,7 +808,7 @@ def test_default_active_subscription_to_non_disabled_one(self): self.assertTrue(storage_mock['subscriptions'][1]['isDefault']) def test_get_subscription(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -828,7 +828,7 @@ def test_get_subscription(self): @mock.patch('azure.cli.core.profiles.get_api_version', autospec=True) def test_subscription_finder_constructor(self, get_api_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) get_api_mock.return_value = '2019-11-01' cli.cloud.endpoints.resource_manager = 'http://foo_arm' finder = SubscriptionFinder(cli) @@ -836,7 +836,7 @@ def test_subscription_finder_constructor(self, get_api_mock): self.assertEqual(result._client._base_url, 'http://foo_arm') def test_get_current_account_user(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -850,7 +850,7 @@ def test_get_current_account_user(self): @mock.patch('azure.cli.core.auth.identity.Identity.get_user_credential', return_value=credential_mock) def test_get_login_credentials(self, get_user_credential_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) # setup storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -874,7 +874,7 @@ def test_get_login_credentials(self, get_user_credential_mock): @mock.patch('azure.cli.core.auth.identity.Identity.get_user_credential', return_value=credential_mock) def test_get_login_credentials_aux_subscriptions(self, get_user_credential_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -903,7 +903,7 @@ def test_get_login_credentials_aux_subscriptions(self, get_user_credential_mock) @mock.patch('azure.cli.core.auth.identity.Identity.get_user_credential', return_value=credential_mock) def test_get_login_credentials_aux_tenants(self, get_user_credential_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -941,7 +941,7 @@ def test_get_login_credentials_aux_tenants(self, get_user_credential_mock): def test_get_login_credentials_msi_system_assigned(self): # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_tenant_id = '12345678-38d6-4fb2-bad9-b7b93a3e1234' test_user = 'systemAssignedIdentity' @@ -964,7 +964,7 @@ def test_get_login_credentials_msi_system_assigned(self): @mock.patch('azure.cli.core.auth.adal_authentication.MSIAuthenticationWrapper', MSRestAzureAuthStub) def test_get_login_credentials_msi_user_assigned_with_client_id(self): # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_tenant_id = '12345678-38d6-4fb2-bad9-b7b93a3e1234' test_user = 'userAssignedIdentity' @@ -988,7 +988,7 @@ def test_get_login_credentials_msi_user_assigned_with_client_id(self): def test_get_login_credentials_msi_user_assigned_with_object_id(self): # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_object_id = '12345678-38d6-4fb2-bad9-b7b93a3e9999' msi_subscription = SubscriptionStub('/subscriptions/12345678-1bf0-4dda-aec3-cb9272f09590', @@ -1011,7 +1011,7 @@ def test_get_login_credentials_msi_user_assigned_with_object_id(self): @mock.patch('azure.cli.core.auth.adal_authentication.MSIAuthenticationWrapper', MSRestAzureAuthStub) def test_get_login_credentials_msi_user_assigned_with_res_id(self): # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_res_id = ('/subscriptions/{}/resourceGroups/r1/providers/Microsoft.ManagedIdentity/' 'userAssignedIdentities/id1').format(test_subscription_id) @@ -1036,7 +1036,7 @@ def test_get_login_credentials_msi_user_assigned_with_res_id(self): def test_get_raw_token(self, get_user_credential_mock): credential_mock_temp = CredentialMock() get_user_credential_mock.return_value = credential_mock_temp - cli = DummyCli() + cli = DummyCli(random_config_dir=True) # setup storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -1083,7 +1083,7 @@ def test_get_raw_token(self, get_user_credential_mock): def test_get_raw_token_for_sp(self, get_service_principal_credential_mock): credential_mock_temp = CredentialMock() get_service_principal_credential_mock.return_value = credential_mock_temp - cli = DummyCli() + cli = DummyCli(random_config_dir=True) # setup storage_mock = {'subscriptions': None} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -1122,7 +1122,7 @@ def test_get_raw_token_for_sp(self, get_service_principal_credential_mock): @mock.patch('azure.cli.core.auth.adal_authentication.MSIAuthenticationWrapper', autospec=True) def test_get_raw_token_msi_system_assigned(self, mock_msi_auth): # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_tenant_id = '12345678-38d6-4fb2-bad9-b7b93a3e1234' test_user = 'systemAssignedIdentity' @@ -1169,7 +1169,7 @@ def test_get_raw_token_in_cloud_console(self, mock_msi_auth, mock_in_cloud_conso mock_in_cloud_console.return_value = True # setup an existing msi subscription - profile = Profile(cli_ctx=DummyCli(), storage={'subscriptions': None}) + profile = Profile(cli_ctx=DummyCli(random_config_dir=True), storage={'subscriptions': None}) test_subscription_id = '12345678-1bf0-4dda-aec3-cb9272f09590' test_tenant_id = '12345678-38d6-4fb2-bad9-b7b93a3e1234' msi_subscription = SubscriptionStub('/subscriptions/' + test_subscription_id, @@ -1212,7 +1212,7 @@ def mi_auth_factory(*args, **kwargs): @mock.patch('azure.cli.core.auth.identity.Identity.logout_user') def test_logout(self, logout_user_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -1230,7 +1230,7 @@ def test_logout(self, logout_user_mock): @mock.patch('azure.cli.core.auth.identity.Identity.logout_all_users') def test_logout_all(self, logout_all_users_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) # setup storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -1258,7 +1258,7 @@ def test_refresh_accounts_one_user_account(self, get_user_credential_mock, creat mock_arm_client.subscriptions.list.return_value = [deepcopy(self.subscription1_raw)] create_subscription_client_mock.return_value = mock_arm_client - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) consolidated = profile._normalize_properties(self.user1, deepcopy([self.subscription1]), False, None, None) @@ -1288,7 +1288,7 @@ def test_refresh_accounts_one_user_account(self, get_user_credential_mock, creat def test_refresh_accounts_one_user_account_one_sp_account(self, get_user_credential_mock, get_service_principal_credential_mock, create_subscription_client_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) sp_id = '44fee498-c798-4ebb-a41f-7bb523bed8d8' storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) @@ -1323,7 +1323,7 @@ def test_refresh_accounts_one_user_account_one_sp_account(self, get_user_credent @mock.patch('azure.cli.core._profile.SubscriptionFinder._create_subscription_client', autospec=True) @mock.patch('azure.cli.core.auth.identity.Identity.get_user_credential', autospec=True) def test_refresh_accounts_with_nothing(self, get_user_credential_mock, create_subscription_client_mock): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) consolidated = profile._normalize_properties(self.user1, deepcopy([self.subscription1]), False, None, None) @@ -1344,7 +1344,7 @@ def test_refresh_accounts_with_nothing(self, get_user_credential_mock, create_su @mock.patch('azure.cli.core.auth.identity.Identity.get_user_credential', autospec=True) def test_login_common_tenant_mfa_warning(self, get_user_credential_mock, create_subscription_client_mock): # Assume 2 tenants. Home tenant tenant1 doesn't require MFA, but tenant2 does - cli = DummyCli() + cli = DummyCli(random_config_dir=True) mock_arm_client = mock.MagicMock() tenant2_mfa_id = 'tenant2-0000-0000-0000-000000000000' mock_arm_client.tenants.list.return_value = [TenantStub(self.tenant_id), TenantStub(tenant2_mfa_id)] @@ -1384,7 +1384,7 @@ def test_login_common_tenant_mfa_warning(self, get_user_credential_mock, create_ # With pytest, use -o log_cli=True to manually check the log def test_get_auth_info_for_newly_created_service_principal(self): - cli = DummyCli() + cli = DummyCli(random_config_dir=True) storage_mock = {'subscriptions': []} profile = Profile(cli_ctx=cli, storage=storage_mock) consolidated = profile._normalize_properties(self.user1, [self.subscription1], False)