diff --git a/awx/api/metadata.py b/awx/api/metadata.py index 0820902cd9..847e353890 100644 --- a/awx/api/metadata.py +++ b/awx/api/metadata.py @@ -23,7 +23,7 @@ from rest_framework.request import clone_request # AWX from awx.api.fields import ChoiceNullField from awx.main.fields import JSONField, ImplicitRoleField -from awx.main.models import InventorySource, NotificationTemplate +from awx.main.models import NotificationTemplate from awx.main.scheduler.kubernetes import PodManager @@ -115,13 +115,6 @@ class Metadata(metadata.SimpleMetadata): if getattr(field, 'write_only', False): field_info['write_only'] = True - # Special handling of inventory source_region choices that vary based on - # selected inventory source. - if field.field_name == 'source_regions': - for cp in ('azure_rm', 'ec2', 'gce'): - get_regions = getattr(InventorySource, 'get_%s_region_choices' % cp) - field_info['%s_region_choices' % cp] = get_regions() - # Special handling of notification configuration where the required properties # are conditional on the type selected. if field.field_name == 'notification_configuration': diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 3d6adc6a78..9cf953262b 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1937,7 +1937,7 @@ class InventorySourceOptionsSerializer(BaseSerializer): class Meta: fields = ('*', 'source', 'source_path', 'source_script', 'source_vars', 'credential', - 'source_regions', 'overwrite', 'overwrite_vars', + 'overwrite', 'overwrite_vars', 'custom_virtualenv', 'timeout', 'verbosity') def get_related(self, obj): @@ -1957,7 +1957,7 @@ class InventorySourceOptionsSerializer(BaseSerializer): return ret def validate(self, attrs): - # TODO: Validate source, validate source_regions + # TODO: Validate source errors = {} source = attrs.get('source', self.instance and self.instance.source or '') diff --git a/awx/main/migrations/0118_v380_inventory_plugins.py b/awx/main/migrations/0118_v380_inventory_plugins.py index 3fddf729e0..d2c9a06398 100644 --- a/awx/main/migrations/0118_v380_inventory_plugins.py +++ b/awx/main/migrations/0118_v380_inventory_plugins.py @@ -3,9 +3,8 @@ import logging import json -from django.db import migrations, models +from django.db import migrations -from awx.main.models.inventory import InventorySource from ._inventory_source_vars import FrozenInjectors @@ -13,15 +12,16 @@ logger = logging.getLogger('awx.main.migrations') BACKUP_FILENAME = '/tmp/tower_migration_inventory_source_vars.json' -def _get_inventory_sources(): - # TODO: Maybe pull this list from an import +def _get_inventory_sources(InventorySource): + # TODO: Maybe pull the list of cloud sources from code return InventorySource.objects.filter(source__in=['ec2', 'gce', 'azure_rm', 'vmware', 'satellite6', 'openstack', 'rhv', 'tower']) def inventory_source_vars_forward(apps, schema_editor): + InventorySource = apps.get_model("main", "InventorySource") source_vars_backup = dict() - for inv_source_obj in _get_inventory_sources(): + for inv_source_obj in _get_inventory_sources(InventorySource): # TODO: Log error if this is false, it shouldn't be false if inv_source_obj.source in FrozenInjectors: source_vars_backup[inv_source_obj.id] = dict(inv_source_obj.source_vars_dict) @@ -66,10 +66,18 @@ class Migration(migrations.Migration): ), migrations.RemoveField( model_name='inventorysource', - name='instance_filter', + name='instance_filters', ), migrations.RemoveField( model_name='inventoryupdate', - name='instance_filter', + name='instance_filters', + ), + migrations.RemoveField( + model_name='inventorysource', + name='source_regions', + ), + migrations.RemoveField( + model_name='inventoryupdate', + name='source_regions', ), ] diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index f34ce3d236..36b358a1bd 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -4,7 +4,6 @@ # Python import datetime import time -import json import logging import re import copy @@ -19,7 +18,6 @@ from django.utils.translation import ugettext_lazy as _ from django.db import transaction from django.core.exceptions import ValidationError from django.utils.timezone import now -from django.utils.encoding import iri_to_uri from django.db.models import Q # REST Framework @@ -56,7 +54,7 @@ from awx.main.models.notifications import ( JobNotificationMixin, ) from awx.main.models.credential.injectors import _openstack_data -from awx.main.utils import _inventory_updates, region_sorting +from awx.main.utils import _inventory_updates from awx.main.utils.safe_yaml import sanitize_jinja @@ -864,11 +862,6 @@ class InventorySourceOptions(BaseModel): default='', help_text=_('Inventory source variables in YAML or JSON format.'), ) - source_regions = models.CharField( - max_length=1024, - blank=True, - default='', - ) overwrite = models.BooleanField( default=False, help_text=_('Overwrite local groups and hosts from remote inventory source.'), @@ -888,79 +881,6 @@ class InventorySourceOptions(BaseModel): default=1, ) - @classmethod - def get_ec2_region_choices(cls): - ec2_region_names = getattr(settings, 'EC2_REGION_NAMES', {}) - ec2_name_replacements = { - 'us': 'US', - 'ap': 'Asia Pacific', - 'eu': 'Europe', - 'sa': 'South America', - } - import boto.ec2 - regions = [('all', 'All')] - for region in boto.ec2.regions(): - label = ec2_region_names.get(region.name, '') - if not label: - label_parts = [] - for part in region.name.split('-'): - part = ec2_name_replacements.get(part.lower(), part.title()) - label_parts.append(part) - label = ' '.join(label_parts) - regions.append((region.name, label)) - return sorted(regions, key=region_sorting) - - @classmethod - def get_gce_region_choices(self): - """Return a complete list of regions in GCE, as a list of - two-tuples. - """ - # It's not possible to get a list of regions from GCE without - # authenticating first. Therefore, use a list from settings. - regions = list(getattr(settings, 'GCE_REGION_CHOICES', [])) - regions.insert(0, ('all', 'All')) - return sorted(regions, key=region_sorting) - - @classmethod - def get_azure_rm_region_choices(self): - """Return a complete list of regions in Microsoft Azure, as a list of - two-tuples. - """ - # It's not possible to get a list of regions from Azure without - # 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_RM_REGION_CHOICES', [])) - regions.insert(0, ('all', 'All')) - return sorted(regions, key=region_sorting) - - @classmethod - def get_vmware_region_choices(self): - """Return a complete list of regions in VMware, as a list of two-tuples - (but note that VMware doesn't actually have regions!). - """ - return [('all', 'All')] - - @classmethod - def get_openstack_region_choices(self): - """I don't think openstack has regions""" - return [('all', 'All')] - - @classmethod - def get_satellite6_region_choices(self): - """Red Hat Satellite 6 region choices (not implemented)""" - return [('all', 'All')] - - @classmethod - def get_rhv_region_choices(self): - """No region supprt""" - return [('all', 'All')] - - @classmethod - def get_tower_region_choices(self): - """No region supprt""" - return [('all', 'All')] - @staticmethod def cloud_credential_validation(source, cred): if not source: @@ -1025,28 +945,6 @@ class InventorySourceOptions(BaseModel): if cred is not None: return cred.pk - def clean_source_regions(self): - regions = self.source_regions - - if self.source in CLOUD_PROVIDERS: - get_regions = getattr(self, 'get_%s_region_choices' % self.source) - valid_regions = [x[0] for x in get_regions()] - region_transform = lambda x: x.strip().lower() - else: - return '' - all_region = region_transform('all') - valid_regions = [region_transform(x) for x in valid_regions] - regions = [region_transform(x) for x in regions.split(',') if x.strip()] - if all_region in regions: - return all_region - invalid_regions = [] - for r in regions: - if r not in valid_regions and r not in invalid_regions: - invalid_regions.append(r) - if invalid_regions: - raise ValidationError(_('Invalid %(source)s region: %(region)s') % { - 'source': self.source, 'region': ', '.join(invalid_regions)}) - return ','.join(regions) source_vars_dict = VarsDictProperty('source_vars') @@ -1550,7 +1448,7 @@ class gce(PluginFileInjector): def inventory_as_dict(self, inventory_update, private_data_dir): ret = super().inventory_as_dict(inventory_update, private_data_dir) - credential = inventory_source.get_cloud_credential() + credential = inventory_update.get_cloud_credential() ret['projects'] = [credential.get_input('project', default='')] return ret diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index 341fcdc82d..cda720b6ab 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -2020,7 +2020,6 @@ class TestInventoryUpdateCredentials(TestJobExecution): task = tasks.RunInventoryUpdate() azure_rm = CredentialType.defaults['azure_rm']() inventory_update.source = 'azure_rm' - inventory_update.source_regions = 'north, south, east, west' def get_cred(): cred = Credential( @@ -2059,7 +2058,6 @@ class TestInventoryUpdateCredentials(TestJobExecution): task = tasks.RunInventoryUpdate() azure_rm = CredentialType.defaults['azure_rm']() inventory_update.source = 'azure_rm' - inventory_update.source_regions = 'all' def get_cred(): cred = Credential( @@ -2097,7 +2095,6 @@ class TestInventoryUpdateCredentials(TestJobExecution): task = tasks.RunInventoryUpdate() gce = CredentialType.defaults['gce']() inventory_update.source = 'gce' - inventory_update.source_regions = 'all' def get_cred(): cred = Credential( diff --git a/awx/main/tests/unit/utils/test_common.py b/awx/main/tests/unit/utils/test_common.py index edacfc1423..8c07020c53 100644 --- a/awx/main/tests/unit/utils/test_common.py +++ b/awx/main/tests/unit/utils/test_common.py @@ -215,11 +215,3 @@ def test_get_custom_venv_choices(): os.path.join(temp_dir, ''), os.path.join(custom_venv_1, '') ] - - -def test_region_sorting(): - s = [('Huey', 'China1'), - ('Dewey', 'UK1'), - ('Lewie', 'US1'), - ('All', 'All')] - assert [x[1] for x in sorted(s, key=common.region_sorting)] == ['All', 'US1', 'China1', 'UK1'] diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py index f34cf4e4d8..a017dba61b 100644 --- a/awx/main/utils/common.py +++ b/awx/main/utils/common.py @@ -45,7 +45,7 @@ __all__ = [ 'get_object_or_400', 'camelcase_to_underscore', 'underscore_to_camelcase', 'memoize', 'memoize_delete', 'get_ansible_version', 'get_licenser', 'get_awx_http_client_headers', 'get_awx_version', 'update_scm_url', 'get_type_for_model', 'get_model_for_type', - 'copy_model_by_class', 'region_sorting', 'copy_m2m_relationships', + 'copy_model_by_class', 'copy_m2m_relationships', 'prefetch_page_capabilities', 'to_python_boolean', 'ignore_inventory_computed_fields', 'ignore_inventory_group_removal', '_inventory_updates', 'get_pk_from_dict', 'getattrd', 'getattr_dne', 'NoDefaultProvided', 'get_current_apps', 'set_current_apps', @@ -87,15 +87,6 @@ def to_python_boolean(value, allow_none=False): raise ValueError(_(u'Unable to convert "%s" to boolean') % value) -def region_sorting(region): - # python3's removal of sorted(cmp=...) is _stupid_ - if region[1].lower() == 'all': - return '' - elif region[1].lower().startswith('us'): - return region[1] - return 'ZZZ' + str(region[1]) - - def camelcase_to_underscore(s): ''' Convert CamelCase names to lowercase_with_underscore. diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 716aea3aa7..cb7dc49e46 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -672,28 +672,6 @@ INV_ENV_VARIABLE_BLOCKED = ("HOME", "USER", "_", "TERM") # -- Amazon EC2 -- # ---------------- -# AWS does not appear to provide pretty region names via any API, so store the -# list of names here. The available region IDs will be pulled from boto. -# http://docs.aws.amazon.com/general/latest/gr/rande.html#ec2_region -EC2_REGION_NAMES = { - 'us-east-1': _('US East (Northern Virginia)'), - 'us-east-2': _('US East (Ohio)'), - 'us-west-2': _('US West (Oregon)'), - 'us-west-1': _('US West (Northern California)'), - 'ca-central-1': _('Canada (Central)'), - 'eu-central-1': _('EU (Frankfurt)'), - 'eu-west-1': _('EU (Ireland)'), - 'eu-west-2': _('EU (London)'), - 'ap-southeast-1': _('Asia Pacific (Singapore)'), - 'ap-southeast-2': _('Asia Pacific (Sydney)'), - 'ap-northeast-1': _('Asia Pacific (Tokyo)'), - 'ap-northeast-2': _('Asia Pacific (Seoul)'), - 'ap-south-1': _('Asia Pacific (Mumbai)'), - 'sa-east-1': _('South America (Sao Paulo)'), - 'us-gov-west-1': _('US West (GovCloud)'), - 'cn-north-1': _('China (Beijing)'), -} - # Inventory variable name/values for determining if host is active/enabled. EC2_ENABLED_VAR = 'ec2_state' EC2_ENABLED_VALUE = 'running' @@ -729,41 +707,6 @@ VMWARE_VALIDATE_CERTS = False # -- Google Compute Engine -- # --------------------------- -# It's not possible to get zones in GCE without authenticating, so we -# provide a list here. -# Source: https://developers.google.com/compute/docs/zones -GCE_REGION_CHOICES = [ - ('us-east1-b', _('US East 1 (B)')), - ('us-east1-c', _('US East 1 (C)')), - ('us-east1-d', _('US East 1 (D)')), - ('us-east4-a', _('US East 4 (A)')), - ('us-east4-b', _('US East 4 (B)')), - ('us-east4-c', _('US East 4 (C)')), - ('us-central1-a', _('US Central (A)')), - ('us-central1-b', _('US Central (B)')), - ('us-central1-c', _('US Central (C)')), - ('us-central1-f', _('US Central (F)')), - ('us-west1-a', _('US West (A)')), - ('us-west1-b', _('US West (B)')), - ('us-west1-c', _('US West (C)')), - ('europe-west1-b', _('Europe West 1 (B)')), - ('europe-west1-c', _('Europe West 1 (C)')), - ('europe-west1-d', _('Europe West 1 (D)')), - ('europe-west2-a', _('Europe West 2 (A)')), - ('europe-west2-b', _('Europe West 2 (B)')), - ('europe-west2-c', _('Europe West 2 (C)')), - ('asia-east1-a', _('Asia East (A)')), - ('asia-east1-b', _('Asia East (B)')), - ('asia-east1-c', _('Asia East (C)')), - ('asia-southeast1-a', _('Asia Southeast (A)')), - ('asia-southeast1-b', _('Asia Southeast (B)')), - ('asia-northeast1-a', _('Asia Northeast (A)')), - ('asia-northeast1-b', _('Asia Northeast (B)')), - ('asia-northeast1-c', _('Asia Northeast (C)')), - ('australia-southeast1-a', _('Australia Southeast (A)')), - ('australia-southeast1-b', _('Australia Southeast (B)')), - ('australia-southeast1-c', _('Australia Southeast (C)')), -] # Inventory variable name/value for determining whether a host is active # in Google Compute Engine. GCE_ENABLED_VAR = 'status' @@ -779,35 +722,6 @@ GCE_INSTANCE_ID_VAR = 'gce_id' # -------------------------------------- # -- Microsoft Azure Resource Manager -- # -------------------------------------- -# It's not possible to get zones in Azure without authenticating, so we -# provide a list here. -AZURE_RM_REGION_CHOICES = [ - ('eastus', _('US East')), - ('eastus2', _('US East 2')), - ('centralus', _('US Central')), - ('northcentralus', _('US North Central')), - ('southcentralus', _('US South Central')), - ('westcentralus', _('US West Central')), - ('westus', _('US West')), - ('westus2', _('US West 2')), - ('canadaeast', _('Canada East')), - ('canadacentral', _('Canada Central')), - ('brazilsouth', _('Brazil South')), - ('northeurope', _('Europe North')), - ('westeurope', _('Europe West')), - ('ukwest', _('UK West')), - ('uksouth', _('UK South')), - ('eastasia', _('Asia East')), - ('southestasia', _('Asia Southeast')), - ('australiaeast', _('Australia East')), - ('australiasoutheast', _('Australia Southeast')), - ('westindia', _('India West')), - ('southindia', _('India South')), - ('japaneast', _('Japan East')), - ('japanwest', _('Japan West')), - ('koreacentral', _('Korea Central')), - ('koreasouth', _('Korea South')), -] AZURE_RM_GROUP_FILTER = r'^.+$' AZURE_RM_HOST_FILTER = r'^.+$' AZURE_RM_ENABLED_VAR = 'powerstate' diff --git a/awx_collection/plugins/modules/tower_inventory_source.py b/awx_collection/plugins/modules/tower_inventory_source.py index 3840806f8f..d3517b3f5a 100644 --- a/awx_collection/plugins/modules/tower_inventory_source.py +++ b/awx_collection/plugins/modules/tower_inventory_source.py @@ -61,10 +61,6 @@ options: description: - Credential to use for the source. type: str - source_regions: - description: - - Regions for cloud provider. - type: str overwrite: description: - Delete child groups and hosts not found in source. @@ -157,7 +153,6 @@ def main(): source_script=dict(), source_vars=dict(type='dict'), credential=dict(), - source_regions=dict(), overwrite=dict(type='bool'), overwrite_vars=dict(type='bool'), custom_virtualenv=dict(), @@ -235,7 +230,6 @@ def main(): OPTIONAL_VARS = ( 'description', 'source', 'source_path', 'source_vars', - 'source_regions', 'overwrite', 'overwrite_vars', 'custom_virtualenv', 'timeout', 'verbosity', 'update_on_launch', 'update_cache_timeout', 'update_on_project_update' diff --git a/awx_collection/test/awx/test_inventory_source.py b/awx_collection/test/awx/test_inventory_source.py index fff6cdd3c3..b27653fb94 100644 --- a/awx_collection/test/awx/test_inventory_source.py +++ b/awx_collection/test/awx/test_inventory_source.py @@ -190,7 +190,6 @@ def test_falsy_value(run_module, admin_user, base_inventory): # overwrite_vars ? ? o o o o o o o o o o o # update_on_launch ? ? o o o o o o o o o o o # UoPL ? ? o - - - - - - - - - - -# source_regions ? ? - o o o - - - - - - - # source_vars* ? ? - o - o o o o o - - - # environmet vars* ? ? o - - - - - - - - - o # source_script ? ? - - - - - - - - - - r diff --git a/awxkit/awxkit/api/pages/inventory.py b/awxkit/awxkit/api/pages/inventory.py index 0976b09afe..ea7e70b3b8 100644 --- a/awxkit/awxkit/api/pages/inventory.py +++ b/awxkit/awxkit/api/pages/inventory.py @@ -500,7 +500,6 @@ class InventorySource(HasCreate, HasNotifications, UnifiedJobTemplate): optional_fields = ( 'source_path', - 'source_regions', 'source_vars', 'timeout', 'overwrite',