mirror of
https://github.com/ansible/awx.git
synced 2026-07-28 00:19:54 -02:30
AAP-73393 - Remove skip_tags character limit by converting to TextField (#16552)
* Optimize HostList API: conditional DISTINCT + composite index on JobHostSummary (#16530) AAP-81517 — Optimize HostList API: conditional DISTINCT + composite index Make .distinct() conditional on host_filter being set — without it the RBAC IN subquery on a direct FK cannot produce duplicates, so DISTINCT is pure overhead. Add composite index (host_id, id DESC) on main_jobhostsummary so the with_latest_summary_id() correlated subquery can use an index-only top-1 scan instead of scanning and sorting. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * Fix: Increase awx-operator molecule timeout to 20m (#16534) The awx-operator molecule kind test intermittently times out after 15 minutes on GitHub Actions runners, causing flaky CI failures. Bump the bash-level timeout from 15m to 20m (step-level timeout-minutes: 60 is unchanged). Closes: AAP-81583 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * AAP-81860 — Eliminate LEFT OUTER JOINs in ActivityStream RBAC query (#16533) * AAP-81860 — Eliminate LEFT OUTER JOINs in ActivityStream RBAC query ActivityStreamAccess.filtered_queryset() used field-traversal Q objects (e.g. Q(host__inventory__in=...)) across 18 M2M relationships, which Django translates into LEFT OUTER JOINs. This forces PostgreSQL to join all intermediary tables before filtering, making it the #2 DB consumer at 483s in a 10-minute Scale Lab window. Replace all M2M field traversals with pk__in subqueries using .through intermediary tables, following the same pattern proven in AAP-81082 (28% improvement for unified job RBAC). This changes the SQL from LEFT OUTER JOIN to IN (SELECT ...) semi-joins, allowing PostgreSQL to skip the unconditional joins. Also: - Remove .distinct() (no longer needed without M2M JOINs) - Remove unnecessary if-truthy checks that evaluated subqueries as boolean before including them (5 extra DB roundtrips per request) - Migrate accessible_pk_qs(user, 'read_role') to access_ids_qs(user, 'view') for direct DAB RBAC API usage * Use .exists() instead of queryset truth-test for auditing_orgs guard Avoids evaluating the full queryset when checking whether the user has auditing orgs — .exists() issues a cheaper SELECT 1 … LIMIT 1 instead. * Restore .exists() guards for resource-type Q branches Re-add conditional guards around inventory, credential, project, job template, workflow job template, and team Q branches. Uses .exists() (cheap SELECT 1 LIMIT 1) instead of the old queryset truth-test to avoid unnecessary query evaluation while still preventing generation of an overly complex query when the user has no access to a given resource type. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * chore: Upgrade kubernetes package to 36.0.2 * feat: remove extra_vars from jobs and unified_jobs list endpoint. Add… (#16461) feat: add exclude query parameter to unified_jobs and jobs list endpoints Allow clients to exclude heavy fields (artifacts, extra_vars) from list responses via ?exclude=artifacts,extra_vars. These fields are now included by default instead of being stripped. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * AAP-80457 - Fix credential_input_source to handle state: absent when target crede… (#16523) Fix credential_input_source to handle state: absent when target credential is missing The credential_input_source module would error when trying to delete a credential input source (state: absent) if the target credential didn't exist. This breaks idempotent playbook runs where cleanup tasks assume resources may already be gone. The fix only applies to state: absent; state: present still correctly fails when the target credential doesn't exist. Co-authored-by: Liam Allen <lallen@redhat.com> * AAP-83163 — Eliminate LEFT JOIN fan-out in user list RBAC query (#16546) Replace legacy Role M2M traversal in UserAccess.filtered_queryset() with DAB's visible_users(), which queries organizational membership through RoleUserAssignment subqueries instead of LEFT OUTER JOINs through the objectrole/roleevaluation tables. Also replace role__in=actor.has_roles.all() in can_admin() with RoleEvaluation._actor_role_filter() to avoid the objectrole JOIN in per-object permission checks. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> * alter_skip_tags_to_textfield * Bump migration number --------- Co-authored-by: Dirk Julich <djulich@redhat.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Rodrigo Toshiaki Horie <rodrigo.horie@hotmail.com> Co-authored-by: Adrià Sala <22398818+adrisala@users.noreply.github.com> Co-authored-by: Peter Braun <pbraun@redhat.com> Co-authored-by: Nick Meyer <nick.a.meyer@icloud.com>
This commit is contained in:
23
awx/main/migrations/0207_alter_skip_tags_to_textfield.py
Normal file
23
awx/main/migrations/0207_alter_skip_tags_to_textfield.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.8 on 2026-07-20 11:07
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0206_jobhostsummary_host_id_idx'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='job',
|
||||
name='skip_tags',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='jobtemplate',
|
||||
name='skip_tags',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
),
|
||||
]
|
||||
@@ -132,8 +132,7 @@ class JobOptions(BaseModel):
|
||||
blank=True,
|
||||
default=False,
|
||||
)
|
||||
skip_tags = models.CharField(
|
||||
max_length=1024,
|
||||
skip_tags = models.TextField(
|
||||
blank=True,
|
||||
default='',
|
||||
)
|
||||
|
||||
@@ -191,6 +191,21 @@ def test_job_accept_empty_tags(job_template_prompts, post, admin_user, mocker):
|
||||
mock_job.signal_start.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.job_runtime_vars
|
||||
def test_job_accept_long_skip_tags(job_template_prompts, post, admin_user, mocker):
|
||||
job_template = job_template_prompts(True)
|
||||
long_skip_tags = ','.join(f'tag{i}' for i in range(500))
|
||||
assert len(long_skip_tags) > 1024
|
||||
|
||||
mock_job = mocker.MagicMock(spec=Job, id=968)
|
||||
|
||||
mocker.patch.object(JobTemplate, 'create_unified_job', return_value=mock_job)
|
||||
mocker.patch('awx.api.serializers.JobSerializer.to_representation')
|
||||
post(reverse('api:job_template_launch', kwargs={'pk': job_template.pk}), {'skip_tags': long_skip_tags}, admin_user, expect=201)
|
||||
JobTemplate.create_unified_job.assert_called_once_with(skip_tags=long_skip_tags)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.job_runtime_vars
|
||||
def test_slice_timeout_forks_need_int(job_template_prompts, post, admin_user, mocker):
|
||||
|
||||
Reference in New Issue
Block a user