From 8440e3f41d9720b58e536da1ffc61914c739a62c Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Thu, 15 Apr 2021 09:45:14 -0400 Subject: [PATCH] Remove ForeignKey relations involving CustomInventoryScript Add migration to carry out corresponding schema change Add data migration to delete inventory sources which are the custom type Split migration into two files data migration touches same rows as schema migration --- awx/api/serializers.py | 5 +- awx/main/constants.py | 5 -- ...6_custom_inventory_scripts_removal_data.py | 19 +++++ .../0137_custom_inventory_scripts_removal.py | 81 +++++++++++++++++++ awx/main/migrations/_inventory_source.py | 19 +++++ awx/main/migrations/_rbac.py | 12 +++ awx/main/models/activity_stream.py | 2 - awx/main/models/base.py | 2 +- awx/main/models/inventory.py | 25 ------ 9 files changed, 135 insertions(+), 35 deletions(-) create mode 100644 awx/main/migrations/0136_custom_inventory_scripts_removal_data.py create mode 100644 awx/main/migrations/0137_custom_inventory_scripts_removal.py diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 1fb0c493f9..266cb01191 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -43,7 +43,7 @@ from polymorphic.models import PolymorphicModel # AWX from awx.main.access import get_user_capabilities -from awx.main.constants import SCHEDULEABLE_PROVIDERS, ACTIVE_STATES, CENSOR_VALUE +from awx.main.constants import ACTIVE_STATES, CENSOR_VALUE from awx.main.models import ( ActivityStream, AdHocCommand, @@ -91,6 +91,7 @@ from awx.main.models import ( WorkflowJobTemplate, WorkflowJobTemplateNode, StdoutMaxBytesExceeded, + CLOUD_INVENTORY_SOURCES, ) from awx.main.models.base import VERBOSITY_CHOICES, NEW_JOB_TYPE_CHOICES from awx.main.models.rbac import get_roles_on_resource, role_summary_fields_generator @@ -4761,7 +4762,7 @@ class ScheduleSerializer(LaunchConfigurationBaseSerializer, SchedulePreviewSeria return summary_fields def validate_unified_job_template(self, value): - if type(value) == InventorySource and value.source not in SCHEDULEABLE_PROVIDERS: + if type(value) == InventorySource and value.source not in CLOUD_INVENTORY_SOURCES: raise serializers.ValidationError(_('Inventory Source must be a cloud resource.')) elif type(value) == Project and value.scm_type == '': raise serializers.ValidationError(_('Manual Project cannot have a schedule set.')) diff --git a/awx/main/constants.py b/awx/main/constants.py index 6a44087c28..b2d62d5ec9 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -7,7 +7,6 @@ from django.utils.translation import ugettext_lazy as _ __all__ = [ 'CLOUD_PROVIDERS', - 'SCHEDULEABLE_PROVIDERS', 'PRIVILEGE_ESCALATION_METHODS', 'ANSI_SGR_PATTERN', 'CAN_CANCEL', @@ -16,10 +15,6 @@ __all__ = [ ] CLOUD_PROVIDERS = ('azure_rm', 'ec2', 'gce', 'vmware', 'openstack', 'rhv', 'satellite6', 'tower') -SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ( - 'custom', - 'scm', -) PRIVILEGE_ESCALATION_METHODS = [ ('sudo', _('Sudo')), ('su', _('Su')), diff --git a/awx/main/migrations/0136_custom_inventory_scripts_removal_data.py b/awx/main/migrations/0136_custom_inventory_scripts_removal_data.py new file mode 100644 index 0000000000..7ade393641 --- /dev/null +++ b/awx/main/migrations/0136_custom_inventory_scripts_removal_data.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.16 on 2021-04-13 19:51 + +from django.db import migrations + +# AWX migration utils +from awx.main.migrations._rbac import delete_all_custom_script_roles +from awx.main.migrations._inventory_source import delete_custom_inv_source + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0135_schedule_sort_fallback_to_id'), + ] + + operations = [ + migrations.RunPython(delete_custom_inv_source), + migrations.RunPython(delete_all_custom_script_roles), + ] diff --git a/awx/main/migrations/0137_custom_inventory_scripts_removal.py b/awx/main/migrations/0137_custom_inventory_scripts_removal.py new file mode 100644 index 0000000000..10bfdc9484 --- /dev/null +++ b/awx/main/migrations/0137_custom_inventory_scripts_removal.py @@ -0,0 +1,81 @@ +# Generated by Django 2.2.16 on 2021-04-13 19:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0136_custom_inventory_scripts_removal_data'), + ] + + operations = [ + migrations.RemoveField( + model_name='activitystream', + name='custom_inventory_script', + ), + migrations.RemoveField( + model_name='inventorysource', + name='source_script', + ), + migrations.RemoveField( + model_name='inventoryupdate', + name='source_script', + ), + migrations.AlterField( + model_name='inventorysource', + name='source', + field=models.CharField( + choices=[ + ('file', 'File, Directory or Script'), + ('scm', 'Sourced from a Project'), + ('ec2', 'Amazon EC2'), + ('gce', 'Google Compute Engine'), + ('azure_rm', 'Microsoft Azure Resource Manager'), + ('vmware', 'VMware vCenter'), + ('satellite6', 'Red Hat Satellite 6'), + ('openstack', 'OpenStack'), + ('rhv', 'Red Hat Virtualization'), + ('tower', 'Ansible Tower'), + ], + default=None, + max_length=32, + ), + ), + migrations.AlterField( + model_name='inventoryupdate', + name='source', + field=models.CharField( + choices=[ + ('file', 'File, Directory or Script'), + ('scm', 'Sourced from a Project'), + ('ec2', 'Amazon EC2'), + ('gce', 'Google Compute Engine'), + ('azure_rm', 'Microsoft Azure Resource Manager'), + ('vmware', 'VMware vCenter'), + ('satellite6', 'Red Hat Satellite 6'), + ('openstack', 'OpenStack'), + ('rhv', 'Red Hat Virtualization'), + ('tower', 'Ansible Tower'), + ], + default=None, + max_length=32, + ), + ), + migrations.AlterUniqueTogether( + name='custominventoryscript', + unique_together=set(), + ), + migrations.RemoveField( + model_name='custominventoryscript', + name='admin_role', + ), + migrations.RemoveField( + model_name='custominventoryscript', + name='organization', + ), + migrations.RemoveField( + model_name='custominventoryscript', + name='read_role', + ), + ] diff --git a/awx/main/migrations/_inventory_source.py b/awx/main/migrations/_inventory_source.py index 40769a0cf9..b12cfa0918 100644 --- a/awx/main/migrations/_inventory_source.py +++ b/awx/main/migrations/_inventory_source.py @@ -90,3 +90,22 @@ def delete_cloudforms_inv_source(apps, schema_editor): if ct: ct.credentials.all().delete() ct.delete() + + +def delete_custom_inv_source(apps, schema_editor): + set_current_apps(apps) + InventorySource = apps.get_model('main', 'InventorySource') + InventoryUpdate = apps.get_model('main', 'InventoryUpdate') + ct, deletions = InventoryUpdate.objects.filter(source='custom').delete() + if ct: + logger.info('deleted {}'.format((ct, deletions))) + update_ct = deletions['main.InventoryUpdate'] + if update_ct: + logger.info('Deleted {} custom inventory script sources.'.format(update_ct)) + ct, deletions = InventorySource.objects.filter(source='custom').delete() + if ct: + logger.info('deleted {}'.format((ct, deletions))) + src_ct = deletions['main.InventorySource'] + if src_ct: + logger.info('Deleted {} custom inventory script updates.'.format(src_ct)) + logger.warning('Custom inventory scripts have been removed, see awx-manage XXXXX') diff --git a/awx/main/migrations/_rbac.py b/awx/main/migrations/_rbac.py index 07284b64cd..480fdd8929 100644 --- a/awx/main/migrations/_rbac.py +++ b/awx/main/migrations/_rbac.py @@ -47,6 +47,18 @@ def delete_all_user_roles(apps, schema_editor): role.delete() +def delete_all_custom_script_roles(apps, schema_editor): + ContentType = apps.get_model('contenttypes', "ContentType") + Role = apps.get_model('main', "Role") + cis_type = ContentType.objects.get(model='custominventoryscript') + role_ct = 0 + for role in Role.objects.filter(content_type=cis_type).iterator(): + role.delete() + role_ct += 1 + if role_ct: + logger.debug('Deleted roles corresponding to custom inventory sources.') + + UNIFIED_ORG_LOOKUPS = { # Job Templates had an implicit organization via their project 'jobtemplate': 'project', diff --git a/awx/main/models/activity_stream.py b/awx/main/models/activity_stream.py index 16e73bef56..e0eafbcfbb 100644 --- a/awx/main/models/activity_stream.py +++ b/awx/main/models/activity_stream.py @@ -74,8 +74,6 @@ class ActivityStream(models.Model): unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+') ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True) schedule = models.ManyToManyField("Schedule", blank=True) - # TODO: migrate away - custom_inventory_script = models.ManyToManyField("CustomInventoryScript", blank=True) execution_environment = models.ManyToManyField("ExecutionEnvironment", blank=True) notification_template = models.ManyToManyField("NotificationTemplate", blank=True) notification = models.ManyToManyField("Notification", blank=True) diff --git a/awx/main/models/base.py b/awx/main/models/base.py index e8c10f5fac..e39891f546 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -62,7 +62,7 @@ PROJECT_UPDATE_JOB_TYPE_CHOICES = [ (PERM_INVENTORY_CHECK, _('Check')), ] -CLOUD_INVENTORY_SOURCES = list(CLOUD_PROVIDERS) + ['scm', 'custom'] +CLOUD_INVENTORY_SOURCES = list(CLOUD_PROVIDERS) + ['scm'] VERBOSITY_CHOICES = [ (0, '0 (Normal)'), diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 58465ba78b..363544e0c6 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -821,7 +821,6 @@ class InventorySourceOptions(BaseModel): ('openstack', _('OpenStack')), ('rhv', _('Red Hat Virtualization')), ('tower', _('Ansible Tower')), - ('custom', _('Custom Script')), ] # From the options of the Django management base command @@ -845,14 +844,6 @@ class InventorySourceOptions(BaseModel): blank=True, default='', ) - # TODO: migrate away - source_script = models.ForeignKey( - 'CustomInventoryScript', - null=True, - default=None, - blank=True, - on_delete=models.SET_NULL, - ) source_vars = models.TextField( blank=True, default='', @@ -1329,7 +1320,6 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin, class CustomInventoryScript(CommonModelNameNotUnique, ResourceMixin): class Meta: app_label = 'main' - unique_together = [('name', 'organization')] ordering = ('name',) script = prevent_search( @@ -1339,21 +1329,6 @@ class CustomInventoryScript(CommonModelNameNotUnique, ResourceMixin): help_text=_('Inventory script contents'), ) ) - organization = models.ForeignKey( - 'Organization', - related_name='custom_inventory_scripts', - help_text=_('Organization owning this inventory script'), - blank=False, - null=True, - on_delete=models.SET_NULL, - ) - - admin_role = ImplicitRoleField( - parent_role='organization.admin_role', - ) - read_role = ImplicitRoleField( - parent_role=['organization.auditor_role', 'organization.member_role', 'admin_role'], - ) def get_absolute_url(self, request=None): return reverse('api:inventory_script_detail', kwargs={'pk': self.pk}, request=request)