From 61093b253250297b3e7c21bebaffa02217b950db Mon Sep 17 00:00:00 2001 From: Alan Rominger Date: Tue, 20 Sep 2022 11:04:37 -0400 Subject: [PATCH] Treat instance_groups prompt as template-less --- awx/api/serializers.py | 10 ++++------ awx/api/views/__init__.py | 3 +++ .../0169_jt_prompt_everything_on_launch.py | 16 ---------------- awx/main/models/ha.py | 11 ----------- awx/main/models/jobs.py | 8 -------- awx/main/models/unified_jobs.py | 12 ++++++++---- awx/main/utils/common.py | 5 ----- 7 files changed, 15 insertions(+), 50 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 23a3da9eae..e7d27183b1 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -4139,12 +4139,12 @@ class JobLaunchSerializer(BaseSerializer): skip_tags = serializers.CharField(required=False, write_only=True, allow_blank=True) limit = serializers.CharField(required=False, write_only=True, allow_blank=True) verbosity = serializers.ChoiceField(required=False, choices=VERBOSITY_CHOICES, write_only=True) - execution_environment = serializers.PrimaryKeyRelatedField(queryset=ExecutionEnvironment.objects.all(), required=False) - labels = serializers.PrimaryKeyRelatedField(many=True, queryset=Label.objects.all(), required=False) + execution_environment = serializers.PrimaryKeyRelatedField(queryset=ExecutionEnvironment.objects.all(), required=False, write_only=True) + labels = serializers.PrimaryKeyRelatedField(many=True, queryset=Label.objects.all(), required=False, write_only=True) forks = serializers.IntegerField(required=False, write_only=True, min_value=0, default=1) job_slice_count = serializers.IntegerField(required=False, write_only=True, min_value=0, default=0) timeout = serializers.IntegerField(required=False, write_only=True, default=0) - instance_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=InstanceGroup.objects.all(), required=False) + instance_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=InstanceGroup.objects.all(), required=False, write_only=True) class Meta: model = JobTemplate @@ -4243,9 +4243,7 @@ class JobLaunchSerializer(BaseSerializer): label_dict = {'id': label.id, 'name': label.name} defaults_dict.setdefault(field_name, []).append(label_dict) elif field_name == 'instance_groups': - for instance_group in obj.instance_groups.all(): - ig_dict = {'id': instance_group.id, 'name': instance_group.name} - defaults_dict.setdefault(field_name, []).append(ig_dict) + defaults_dict[field_name] = [] else: defaults_dict[field_name] = getattr(obj, field_name) return defaults_dict diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 9b34f0f794..dbfedba2e6 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -2398,6 +2398,9 @@ class JobTemplateLaunch(RetrieveAPIView): elif isinstance(getattr(obj.__class__, field).field, ForeignKey): data[field] = getattrd(obj, "%s.%s" % (field, 'id'), None) elif isinstance(getattr(obj.__class__, field).field, ManyToManyField): + if field == 'instance_groups': + data[field] = [] + continue data[field] = [item.id for item in getattr(obj, field).all()] else: data[field] = getattr(obj, field) diff --git a/awx/main/migrations/0169_jt_prompt_everything_on_launch.py b/awx/main/migrations/0169_jt_prompt_everything_on_launch.py index 8704b94446..b31f66e139 100644 --- a/awx/main/migrations/0169_jt_prompt_everything_on_launch.py +++ b/awx/main/migrations/0169_jt_prompt_everything_on_launch.py @@ -175,22 +175,6 @@ class Migration(migrations.Migration): ('joblaunchconfig', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.joblaunchconfig')), ], ), - migrations.CreateModel( - name='JobInstanceGroupMembership', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('position', models.PositiveIntegerField(db_index=True, default=None, null=True)), - ('instancegroup', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.instancegroup')), - ('unifiedjob', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.job')), - ], - ), - migrations.AddField( - model_name='job', - name='instance_groups', - field=awx.main.fields.OrderedManyToManyField( - blank=True, editable=False, related_name='job_instance_groups', through='main.JobInstanceGroupMembership', to='main.InstanceGroup' - ), - ), migrations.AddField( model_name='joblaunchconfig', name='instance_groups', diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 9509523e77..eeed06bc60 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -436,17 +436,6 @@ class InventoryInstanceGroupMembership(models.Model): ) -class JobInstanceGroupMembership(models.Model): - - unifiedjob = models.ForeignKey('Job', on_delete=models.CASCADE) - instancegroup = models.ForeignKey('InstanceGroup', on_delete=models.CASCADE) - position = models.PositiveIntegerField( - null=True, - default=None, - db_index=True, - ) - - class JobLaunchConfigInstanceGroupMembership(models.Model): joblaunchconfig = models.ForeignKey('JobLaunchConfig', on_delete=models.CASCADE) diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index e9cdfd5ee7..84013ea758 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -292,7 +292,6 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour 'job_slice_number', 'job_slice_count', 'execution_environment', - 'instance_groups', ] ) @@ -605,13 +604,6 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana default=1, help_text=_("If ran as part of sliced jobs, the total number of slices. " "If 1, job is not part of a sliced job."), ) - instance_groups = OrderedManyToManyField( - 'InstanceGroup', - related_name='job_instance_groups', - blank=True, - editable=False, - through='JobInstanceGroupMembership', - ) def _get_parent_field_name(self): return 'job_template' diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index d5aadfe72e..b99d72c2eb 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -332,10 +332,11 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, ExecutionEn return NotificationTemplate.objects.none() - def create_unified_job(self, **kwargs): + def create_unified_job(self, instance_groups=None, **kwargs): """ Create a new unified job based on this unified job template. """ + # TODO: rename kwargs to prompts, to set expectation that these are runtime values new_job_passwords = kwargs.pop('survey_passwords', {}) eager_fields = kwargs.pop('_eager_fields', None) @@ -382,8 +383,8 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, ExecutionEn unified_job.survey_passwords = new_job_passwords kwargs['survey_passwords'] = new_job_passwords # saved in config object for relaunch - if kwargs.get('instance_groups'): - unified_job.preferred_instance_groups_cache = [ig.id for ig in kwargs['instance_groups']] + if instance_groups: + unified_job.preferred_instance_groups_cache = [ig.id for ig in instance_groups] else: unified_job.preferred_instance_groups_cache = unified_job._get_preferred_instance_group_cache() @@ -415,7 +416,10 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, ExecutionEn unified_job.handle_extra_data(validated_kwargs['extra_vars']) # Create record of provided prompts for relaunch and rescheduling - unified_job.create_config_from_prompts(kwargs, parent=self) + config = unified_job.create_config_from_prompts(kwargs, parent=self) + if instance_groups: + for ig in instance_groups: + config.instance_groups.add(ig) # manually issue the create activity stream entry _after_ M2M relations # have been associated to the UJ diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py index 3366190ecf..5d06185f78 100644 --- a/awx/main/utils/common.py +++ b/awx/main/utils/common.py @@ -531,11 +531,6 @@ def copy_m2m_relationships(obj1, obj2, fields, kwargs=None): src_field_value = getattr(obj1, field_name) if kwargs and field_name in kwargs: override_field_val = kwargs[field_name] - if field_name == 'instance_groups': - # instance_groups are a list but we need to preserve the order - for ig_id in override_field_val: - getattr(obj2, field_name).add(ig_id) - continue if isinstance(override_field_val, (set, list, QuerySet)): # Labels are additive so we are going to add any src labels in addition to the override labels if field_name == 'labels':