diff --git a/awx/api/metadata.py b/awx/api/metadata.py index 87aec4b69f..7beb3bd5ad 100644 --- a/awx/api/metadata.py +++ b/awx/api/metadata.py @@ -89,7 +89,7 @@ class Metadata(metadata.SimpleMetadata): # Special handling of inventory source_region choices that vary based on # selected inventory source. if field.field_name == 'source_regions': - for cp in ('azure', 'ec2', 'gce'): + for cp in ('azure_rm', 'ec2', 'gce'): get_regions = getattr(InventorySource, 'get_%s_region_choices' % cp) field_info['%s_region_choices' % cp] = get_regions() diff --git a/awx/main/constants.py b/awx/main/constants.py index 10be060094..4ff22662b3 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -5,7 +5,7 @@ import re from django.utils.translation import ugettext_lazy as _ -CLOUD_PROVIDERS = ('azure', 'azure_rm', 'ec2', 'gce', 'rax', 'vmware', 'openstack', 'satellite6', 'cloudforms') +CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'satellite6', 'cloudforms') SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom', 'scm',) PRIVILEGE_ESCALATION_METHODS = [ ('sudo', _('Sudo')), ('su', _('Su')), ('pbrun', _('Pbrun')), ('pfexec', _('Pfexec')), ('dzdo', _('DZDO')), ('pmrun', _('Pmrun')), ('runas', _('Runas'))] ANSI_SGR_PATTERN = re.compile(r'\x1b\[[0-9;]*m') diff --git a/awx/main/management/commands/inventory_import.py b/awx/main/management/commands/inventory_import.py index aa64822bfe..d84d70f2ea 100644 --- a/awx/main/management/commands/inventory_import.py +++ b/awx/main/management/commands/inventory_import.py @@ -194,7 +194,6 @@ def load_inventory_source(source, group_filter_re=None, ''' # Sanity check: We sanitize these module names for our API but Ansible proper doesn't follow # good naming conventions - source = source.replace('azure.py', 'windows_azure.py') source = source.replace('satellite6.py', 'foreman.py') source = source.replace('vmware.py', 'vmware_inventory.py') if not os.path.exists(source): diff --git a/awx/main/models/base.py b/awx/main/models/base.py index 7e22acd3ad..84e90fede4 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -52,7 +52,7 @@ PROJECT_UPDATE_JOB_TYPE_CHOICES = [ (PERM_INVENTORY_CHECK, _('Check')), ] -CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure', 'azure_rm', 'openstack', 'custom', 'satellite6', 'cloudforms', 'scm',] +CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure_rm', 'openstack', 'custom', 'satellite6', 'cloudforms', 'scm',] VERBOSITY_CHOICES = [ (0, '0 (Normal)'), diff --git a/awx/main/models/credential.py b/awx/main/models/credential.py index 9b81498bfa..5a3f0b9662 100644 --- a/awx/main/models/credential.py +++ b/awx/main/models/credential.py @@ -57,7 +57,6 @@ class V1Credential(object): ('satellite6', 'Red Hat Satellite 6'), ('cloudforms', 'Red Hat CloudForms'), ('gce', 'Google Compute Engine'), - ('azure', 'Microsoft Azure Classic (deprecated)'), ('azure_rm', 'Microsoft Azure Resource Manager'), ('openstack', 'OpenStack'), ('insights', 'Insights'), @@ -934,35 +933,6 @@ def gce(cls): ) -@CredentialType.default -def azure(cls): - return cls( - kind='cloud', - name='Microsoft Azure Classic (deprecated)', - managed_by_tower=True, - inputs={ - 'fields': [{ - 'id': 'username', - 'label': 'Subscription ID', - 'type': 'string', - 'help_text': ('Subscription ID is an Azure construct, which is ' - 'mapped to a username.') - }, { - 'id': 'ssh_key_data', - 'label': 'Management Certificate', - 'type': 'string', - 'format': 'ssh_private_key', - 'secret': True, - 'multiline': True, - 'help_text': ('Paste the contents of the PEM file that corresponds ' - 'to the certificate you uploaded in the Microsoft ' - 'Azure console.') - }], - 'required': ['username', 'ssh_key_data'], - } - ) - - @CredentialType.default def azure_rm(cls): return cls( diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index e13db5f749..7b5e3d3dfa 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -867,7 +867,6 @@ class InventorySourceOptions(BaseModel): ('scm', _('Sourced from a Project')), ('ec2', _('Amazon EC2')), ('gce', _('Google Compute Engine')), - ('azure', _('Microsoft Azure Classic (deprecated)')), ('azure_rm', _('Microsoft Azure Resource Manager')), ('vmware', _('VMware vCenter')), ('satellite6', _('Red Hat Satellite 6')), @@ -1087,7 +1086,7 @@ class InventorySourceOptions(BaseModel): return regions @classmethod - def get_azure_region_choices(self): + def get_azure_rm_region_choices(self): """Return a complete list of regions in Microsoft Azure, as a list of two-tuples. """ @@ -1095,14 +1094,10 @@ class InventorySourceOptions(BaseModel): # authenticating first (someone reading these might think there's # a pattern here!). Therefore, you guessed it, use a list from # settings. - regions = list(getattr(settings, 'AZURE_REGION_CHOICES', [])) + regions = list(getattr(settings, 'AZURE_RM_REGION_CHOICES', [])) regions.insert(0, ('all', 'All')) return regions - @classmethod - def get_azure_rm_region_choices(self): - return InventorySourceOptions.get_azure_region_choices() - @classmethod def get_vmware_region_choices(self): """Return a complete list of regions in VMware, as a list of two-tuples diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 2c884802c2..18f1ed5be3 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -1054,9 +1054,6 @@ class RunJob(BaseTask): env['GCE_EMAIL'] = cloud_cred.username env['GCE_PROJECT'] = cloud_cred.project env['GCE_PEM_FILE_PATH'] = cred_files.get(cloud_cred, '') - elif cloud_cred and cloud_cred.kind == 'azure': - env['AZURE_SUBSCRIPTION_ID'] = cloud_cred.username - env['AZURE_CERT_PATH'] = cred_files.get(cloud_cred, '') elif cloud_cred and cloud_cred.kind == 'azure_rm': if len(cloud_cred.client) and len(cloud_cred.tenant): env['AZURE_CLIENT_ID'] = cloud_cred.client @@ -1616,8 +1613,8 @@ class RunInventoryUpdate(BaseTask): If no private data is needed, return None. """ private_data = {'credentials': {}} - # If this is Microsoft Azure or GCE, return the RSA key - if inventory_update.source in ('azure', 'gce'): + # If this is GCE, return the RSA key + if inventory_update.source == 'gce': credential = inventory_update.credential private_data['credentials'][credential] = decrypt_field(credential, 'ssh_key_data') return private_data @@ -1847,9 +1844,6 @@ class RunInventoryUpdate(BaseTask): env['EC2_INI_PATH'] = cloud_credential elif inventory_update.source == 'vmware': env['VMWARE_INI_PATH'] = cloud_credential - elif inventory_update.source == 'azure': - env['AZURE_SUBSCRIPTION_ID'] = passwords.get('source_username', '') - env['AZURE_CERT_PATH'] = cloud_credential elif inventory_update.source == 'azure_rm': if len(passwords.get('source_client', '')) and \ len(passwords.get('source_tenant', '')): diff --git a/awx/main/tests/functional/api/test_credential.py b/awx/main/tests/functional/api/test_credential.py index 8063ff01e7..feebfc08f4 100644 --- a/awx/main/tests/functional/api/test_credential.py +++ b/awx/main/tests/functional/api/test_credential.py @@ -1071,43 +1071,6 @@ def test_gce_create_ok(post, organization, admin, version, params): assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY -# -# Azure Classic -# -@pytest.mark.django_db -@pytest.mark.parametrize('version, params', [ - ['v1', { - 'kind': 'azure', - 'name': 'Best credential ever', - 'username': 'some_username', - 'ssh_key_data': EXAMPLE_PRIVATE_KEY - }], - ['v2', { - 'credential_type': 1, - 'name': 'Best credential ever', - 'inputs': { - 'username': 'some_username', - 'ssh_key_data': EXAMPLE_PRIVATE_KEY - } - }] -]) -def test_azure_create_ok(post, organization, admin, version, params): - azure = CredentialType.defaults['azure']() - azure.save() - params['organization'] = organization.id - response = post( - reverse('api:credential_list', kwargs={'version': version}), - params, - admin - ) - assert response.status_code == 201 - - assert Credential.objects.count() == 1 - cred = Credential.objects.all()[:1].get() - assert cred.inputs['username'] == 'some_username' - assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY - - # # Azure Resource Manager # diff --git a/awx/main/tests/functional/test_credential.py b/awx/main/tests/functional/test_credential.py index 4a51565d04..b4dd0cb0e4 100644 --- a/awx/main/tests/functional/test_credential.py +++ b/awx/main/tests/functional/test_credential.py @@ -19,7 +19,6 @@ EXAMPLE_ENCRYPTED_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nProc-Type: 4,ENCRY def test_default_cred_types(): assert sorted(CredentialType.defaults.keys()) == [ 'aws', - 'azure', 'azure_rm', 'cloudforms', 'gce', diff --git a/awx/main/tests/functional/test_credential_migration.py b/awx/main/tests/functional/test_credential_migration.py index b5453c9a0d..3494545501 100644 --- a/awx/main/tests/functional/test_credential_migration.py +++ b/awx/main/tests/functional/test_credential_migration.py @@ -269,22 +269,6 @@ def test_gce_migration(): assert Credential.objects.count() == 1 -@pytest.mark.django_db -def test_azure_classic_migration(): - cred = Credential(name='My Credential') - with migrate(cred, 'azure'): - cred.__dict__.update({ - 'username': 'bob', - 'ssh_key_data': EXAMPLE_PRIVATE_KEY - }) - - assert cred.credential_type.name == 'Microsoft Azure Classic (deprecated)' - assert cred.inputs['username'] == 'bob' - assert cred.inputs['ssh_key_data'].startswith('$encrypted$') - assert decrypt_field(cred, 'ssh_key_data') == EXAMPLE_PRIVATE_KEY - assert Credential.objects.count() == 1 - - @pytest.mark.django_db def test_azure_rm_migration(): cred = Credential(name='My Credential') diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index 99ad34d766..dfaeab121b 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -533,29 +533,6 @@ class TestJobCredentials(TestJobExecution): self.run_pexpect.side_effect = run_pexpect_side_effect self.task.run(self.pk) - def test_azure_credentials(self): - azure = CredentialType.defaults['azure']() - credential = Credential( - pk=1, - credential_type=azure, - inputs = { - 'username': 'bob', - 'ssh_key_data': self.EXAMPLE_PRIVATE_KEY - } - ) - credential.inputs['ssh_key_data'] = encrypt_field(credential, 'ssh_key_data') - self.instance.extra_credentials.add(credential) - - def run_pexpect_side_effect(*args, **kwargs): - args, cwd, env, stdout = args - assert env['AZURE_SUBSCRIPTION_ID'] == 'bob' - ssh_key_data = env['AZURE_CERT_PATH'] - assert open(ssh_key_data, 'rb').read() == self.EXAMPLE_PRIVATE_KEY - return ['successful', 0] - - self.run_pexpect.side_effect = run_pexpect_side_effect - self.task.run(self.pk) - def test_azure_rm_with_tenant(self): azure = CredentialType.defaults['azure_rm']() credential = Credential( @@ -1027,29 +1004,25 @@ class TestJobCredentials(TestJobExecution): gce_credential.inputs['ssh_key_data'] = encrypt_field(gce_credential, 'ssh_key_data') self.instance.extra_credentials.add(gce_credential) - azure = CredentialType.defaults['azure']() - azure_credential = Credential( + azure_rm = CredentialType.defaults['azure_rm']() + azure_rm_credential = Credential( pk=2, - credential_type=azure, + credential_type=azure_rm, inputs = { - 'username': 'joe', - 'ssh_key_data': 'AZURE: %s' % self.EXAMPLE_PRIVATE_KEY + 'subscription': 'some-subscription', + 'username': 'bob', + 'password': 'secret' } ) - azure_credential.inputs['ssh_key_data'] = encrypt_field(azure_credential, 'ssh_key_data') - self.instance.extra_credentials.add(azure_credential) + azure_rm_credential.inputs['secret'] = encrypt_field(azure_rm_credential, 'secret') + self.instance.extra_credentials.add(azure_rm_credential) def run_pexpect_side_effect(*args, **kwargs): args, cwd, env, stdout = args - assert env['GCE_EMAIL'] == 'bob' - assert env['GCE_PROJECT'] == 'some-project' - ssh_key_data = env['GCE_PEM_FILE_PATH'] - assert open(ssh_key_data, 'rb').read() == 'GCE: %s' % self.EXAMPLE_PRIVATE_KEY - - assert env['AZURE_SUBSCRIPTION_ID'] == 'joe' - ssh_key_data = env['AZURE_CERT_PATH'] - assert open(ssh_key_data, 'rb').read() == 'AZURE: %s' % self.EXAMPLE_PRIVATE_KEY + assert env['AZURE_SUBSCRIPTION_ID'] == 'some-subscription' + assert env['AZURE_AD_USER'] == 'bob' + assert env['AZURE_PASSWORD'] == 'secret' return ['successful', 0] @@ -1246,31 +1219,6 @@ class TestInventoryUpdateCredentials(TestJobExecution): self.run_pexpect.side_effect = run_pexpect_side_effect self.task.run(self.pk) - def test_azure_source(self): - azure = CredentialType.defaults['azure']() - self.instance.source = 'azure' - self.instance.credential = Credential( - pk=1, - credential_type=azure, - inputs = { - 'username': 'bob', - 'ssh_key_data': self.EXAMPLE_PRIVATE_KEY - } - ) - self.instance.credential.inputs['ssh_key_data'] = encrypt_field( - self.instance.credential, 'ssh_key_data' - ) - - def run_pexpect_side_effect(*args, **kwargs): - args, cwd, env, stdout = args - assert env['AZURE_SUBSCRIPTION_ID'] == 'bob' - ssh_key_data = env['AZURE_CERT_PATH'] - assert open(ssh_key_data, 'rb').read() == self.EXAMPLE_PRIVATE_KEY - return ['successful', 0] - - self.run_pexpect.side_effect = run_pexpect_side_effect - self.task.run(self.pk) - def test_gce_source(self): gce = CredentialType.defaults['gce']() self.instance.source = 'gce' diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index c4af5d8d10..29c40dc230 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -770,14 +770,12 @@ GCE_HOST_FILTER = r'^.+$' GCE_EXCLUDE_EMPTY_GROUPS = True GCE_INSTANCE_ID_VAR = None - -# ------------------- -# -- Microsoft Azure -- -# ------------------- - +# -------------------------------------- +# -- Microsoft Azure Resource Manager -- +# -------------------------------------- # It's not possible to get zones in Azure without authenticating, so we # provide a list here. -AZURE_REGION_CHOICES = [ +AZURE_RM_REGION_CHOICES = [ ('eastus', _('US East')), ('eastus2', _('US East 2')), ('centralus', _('US Central')), @@ -804,23 +802,8 @@ AZURE_REGION_CHOICES = [ ('koreacentral', _('Korea Central')), ('koreasouth', _('Korea South')), ] -AZURE_REGIONS_BLACKLIST = [] +AZURE_RM_REGIONS_BLACKLIST = [] -# Inventory variable name/value for determining whether a host is active -# in Microsoft Azure. -AZURE_ENABLED_VAR = 'instance_status' -AZURE_ENABLED_VALUE = 'ReadyRole' - -# Filter for allowed group and host names when importing inventory from -# Microsoft Azure. -AZURE_GROUP_FILTER = r'^.+$' -AZURE_HOST_FILTER = r'^.+$' -AZURE_EXCLUDE_EMPTY_GROUPS = True -AZURE_INSTANCE_ID_VAR = 'private_id' - -# -------------------------------------- -# -- Microsoft Azure Resource Manager -- -# -------------------------------------- AZURE_RM_GROUP_FILTER = r'^.+$' AZURE_RM_HOST_FILTER = r'^.+$' AZURE_RM_ENABLED_VAR = 'powerstate'