mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 02:19:58 -03:30
[constructed-inventory] Backlink events to real hosts and summaries to both hosts (#13718)
* Backlink events to real hosts and summaries to both hosts * Prevent error when original host is deleted during job run * No duplicate entries, review suggestion from Rick * Change word tense in help text, dict style adjustments From code review Co-authored-by: Rick Elrod <rick@elrod.me> * Back out new variable for constructed host id --------- Co-authored-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
parent
b88d9f4731
commit
3f5a4cb6f1
@ -158,6 +158,7 @@ SUMMARIZABLE_FK_FIELDS = {
|
||||
'kind',
|
||||
),
|
||||
'host': DEFAULT_SUMMARY_FIELDS,
|
||||
'constructed_host': DEFAULT_SUMMARY_FIELDS,
|
||||
'group': DEFAULT_SUMMARY_FIELDS,
|
||||
'default_environment': DEFAULT_SUMMARY_FIELDS + ('image',),
|
||||
'execution_environment': DEFAULT_SUMMARY_FIELDS + ('image',),
|
||||
@ -1903,6 +1904,10 @@ class HostSerializer(BaseSerializerWithVariables):
|
||||
group_list = [{'id': g.id, 'name': g.name} for g in obj.groups.all().order_by('id')[:5]]
|
||||
group_cnt = obj.groups.count()
|
||||
d.setdefault('groups', {'count': group_cnt, 'results': group_list})
|
||||
if obj.inventory.kind == 'constructed':
|
||||
summaries_qs = obj.constructed_host_summaries
|
||||
else:
|
||||
summaries_qs = obj.job_host_summaries
|
||||
d.setdefault(
|
||||
'recent_jobs',
|
||||
[
|
||||
@ -1913,7 +1918,7 @@ class HostSerializer(BaseSerializerWithVariables):
|
||||
'status': j.job.status,
|
||||
'finished': j.job.finished,
|
||||
}
|
||||
for j in obj.job_host_summaries.select_related('job__job_template').order_by('-created').defer('job__extra_vars', 'job__artifacts')[:5]
|
||||
for j in summaries_qs.select_related('job__job_template').order_by('-created').defer('job__extra_vars', 'job__artifacts')[:5]
|
||||
],
|
||||
)
|
||||
return d
|
||||
@ -4140,6 +4145,7 @@ class JobHostSummarySerializer(BaseSerializer):
|
||||
'-description',
|
||||
'job',
|
||||
'host',
|
||||
'constructed_host',
|
||||
'host_name',
|
||||
'changed',
|
||||
'dark',
|
||||
|
||||
@ -122,4 +122,17 @@ class Migration(migrations.Migration):
|
||||
help_text='This field is deprecated and will be removed in a future release. Regex where only matching hosts will be imported.',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='jobhostsummary',
|
||||
name='constructed_host',
|
||||
field=models.ForeignKey(
|
||||
default=None,
|
||||
editable=False,
|
||||
help_text='Only for jobs run against constructed inventories, this links to the host inside the constructed inventory.',
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='constructed_host_summaries',
|
||||
to='main.host',
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@ -7,6 +7,7 @@ from collections import defaultdict
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import models, DatabaseError
|
||||
from django.db.models.functions import Cast
|
||||
from django.utils.dateparse import parse_datetime
|
||||
from django.utils.text import Truncator
|
||||
from django.utils.timezone import utc, now
|
||||
@ -538,23 +539,36 @@ class JobEvent(BasePlaybookEvent):
|
||||
|
||||
from awx.main.models import Host, JobHostSummary # circular import
|
||||
|
||||
all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name')
|
||||
if self.job.inventory.kind == 'constructed':
|
||||
all_hosts = Host.objects.filter(id__in=self.job.inventory.hosts.values_list(Cast('instance_id', output_field=models.IntegerField()))).only(
|
||||
'id', 'name'
|
||||
)
|
||||
constructed_host_map = self.host_map
|
||||
host_map = {host.name: host.id for host in all_hosts}
|
||||
else:
|
||||
all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name')
|
||||
constructed_host_map = {}
|
||||
host_map = self.host_map
|
||||
|
||||
existing_host_ids = set(h.id for h in all_hosts)
|
||||
|
||||
summaries = dict()
|
||||
updated_hosts_list = list()
|
||||
for host in hostnames:
|
||||
updated_hosts_list.append(host.lower())
|
||||
host_id = self.host_map.get(host, None)
|
||||
host_id = host_map.get(host)
|
||||
if host_id not in existing_host_ids:
|
||||
host_id = None
|
||||
constructed_host_id = constructed_host_map.get(host)
|
||||
host_stats = {}
|
||||
for stat in ('changed', 'dark', 'failures', 'ignored', 'ok', 'processed', 'rescued', 'skipped'):
|
||||
try:
|
||||
host_stats[stat] = self.event_data.get(stat, {}).get(host, 0)
|
||||
except AttributeError: # in case event_data[stat] isn't a dict.
|
||||
pass
|
||||
summary = JobHostSummary(created=now(), modified=now(), job_id=job.id, host_id=host_id, host_name=host, **host_stats)
|
||||
summary = JobHostSummary(
|
||||
created=now(), modified=now(), job_id=job.id, host_id=host_id, constructed_host_id=constructed_host_id, host_name=host, **host_stats
|
||||
)
|
||||
summary.failed = bool(summary.dark or summary.failures)
|
||||
summaries[(host_id, host)] = summary
|
||||
|
||||
|
||||
@ -569,12 +569,7 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana
|
||||
default=None,
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
hosts = models.ManyToManyField(
|
||||
'Host',
|
||||
related_name='jobs',
|
||||
editable=False,
|
||||
through='JobHostSummary',
|
||||
)
|
||||
hosts = models.ManyToManyField('Host', related_name='jobs', editable=False, through='JobHostSummary', through_fields=('job', 'host'))
|
||||
artifacts = JSONBlob(
|
||||
default=dict,
|
||||
blank=True,
|
||||
@ -1059,6 +1054,15 @@ class JobHostSummary(CreatedModifiedModel):
|
||||
editable=False,
|
||||
)
|
||||
host = models.ForeignKey('Host', related_name='job_host_summaries', null=True, default=None, on_delete=models.SET_NULL, editable=False)
|
||||
constructed_host = models.ForeignKey(
|
||||
'Host',
|
||||
related_name='constructed_host_summaries',
|
||||
null=True,
|
||||
default=None,
|
||||
on_delete=models.SET_NULL,
|
||||
editable=False,
|
||||
help_text='Only for jobs run against constructed inventories, this links to the host inside the constructed inventory.',
|
||||
)
|
||||
|
||||
host_name = models.CharField(
|
||||
max_length=1024,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user