mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 08:21:15 +03:00
Merge pull request #3893 from AlanCoding/replace_job_origin
Replace JobOrigin model with ActivityStream.action_node field Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
commit
d7c33a7246
@ -4984,7 +4984,7 @@ class ActivityStreamSerializer(BaseSerializer):
|
||||
class Meta:
|
||||
model = ActivityStream
|
||||
fields = ('*', '-name', '-description', '-created', '-modified', 'timestamp', 'operation',
|
||||
'changes', 'object1', 'object2', 'object_association', 'object_type')
|
||||
'changes', 'object1', 'object2', 'object_association', 'action_node', 'object_type')
|
||||
|
||||
def get_fields(self):
|
||||
ret = super(ActivityStreamSerializer, self).get_fields()
|
||||
|
31
awx/main/migrations/0080_v360_replace_job_origin.py
Normal file
31
awx/main/migrations/0080_v360_replace_job_origin.py
Normal file
@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-05-14 14:51
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0079_v360_rm_implicit_oauth2_apps'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='joborigin',
|
||||
name='instance',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='joborigin',
|
||||
name='unified_job',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='activitystream',
|
||||
name='action_node',
|
||||
field=models.CharField(blank=True, default='', editable=False, help_text='The cluster node the activity took place on.', max_length=512),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='JobOrigin',
|
||||
),
|
||||
]
|
@ -35,7 +35,7 @@ from awx.main.models.ad_hoc_commands import AdHocCommand # noqa
|
||||
from awx.main.models.schedules import Schedule # noqa
|
||||
from awx.main.models.activity_stream import ActivityStream # noqa
|
||||
from awx.main.models.ha import ( # noqa
|
||||
Instance, InstanceGroup, JobOrigin, TowerScheduleState,
|
||||
Instance, InstanceGroup, TowerScheduleState,
|
||||
)
|
||||
from awx.main.models.rbac import ( # noqa
|
||||
Role, batch_role_ancestor_rebuilding, get_roles_on_resource,
|
||||
|
@ -7,6 +7,7 @@ from awx.main.fields import JSONField
|
||||
|
||||
# Django
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
@ -35,6 +36,13 @@ class ActivityStream(models.Model):
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
changes = models.TextField(blank=True)
|
||||
deleted_actor = JSONField(null=True)
|
||||
action_node = models.CharField(
|
||||
blank=True,
|
||||
default='',
|
||||
editable=False,
|
||||
max_length=512,
|
||||
help_text=_("The cluster node the activity took place on."),
|
||||
)
|
||||
|
||||
object_relationship_type = models.TextField(blank=True)
|
||||
object1 = models.TextField()
|
||||
@ -78,7 +86,13 @@ class ActivityStream(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
operation = self.operation if 'operation' in self.__dict__ else '_delayed_'
|
||||
timestamp = self.timestamp.isoformat() if 'timestamp' in self.__dict__ else '_delayed_'
|
||||
if 'timestamp' in self.__dict__:
|
||||
if self.timestamp:
|
||||
timestamp = self.timestamp.isoformat()
|
||||
else:
|
||||
timestamp = self.timestamp
|
||||
else:
|
||||
timestamp = '_delayed_'
|
||||
return u'%s-%s-pk=%s' % (operation, timestamp, self.pk)
|
||||
|
||||
def get_absolute_url(self, request=None):
|
||||
@ -97,4 +111,7 @@ class ActivityStream(models.Model):
|
||||
if 'update_fields' in kwargs and 'deleted_actor' not in kwargs['update_fields']:
|
||||
kwargs['update_fields'].append('deleted_actor')
|
||||
|
||||
hostname_char_limit = self._meta.get_field('action_node').max_length
|
||||
self.action_node = settings.CLUSTER_HOST_ID[:hostname_char_limit]
|
||||
|
||||
super(ActivityStream, self).save(*args, **kwargs)
|
||||
|
@ -19,14 +19,11 @@ from awx.api.versioning import reverse
|
||||
from awx.main.managers import InstanceManager, InstanceGroupManager
|
||||
from awx.main.fields import JSONField
|
||||
from awx.main.models.base import BaseModel, HasEditsMixin
|
||||
from awx.main.models.inventory import InventoryUpdate
|
||||
from awx.main.models.jobs import Job
|
||||
from awx.main.models.projects import ProjectUpdate
|
||||
from awx.main.models.unified_jobs import UnifiedJob
|
||||
from awx.main.utils import get_cpu_capacity, get_mem_capacity, get_system_task_capacity
|
||||
from awx.main.models.mixins import RelatedJobsMixin
|
||||
|
||||
__all__ = ('Instance', 'InstanceGroup', 'JobOrigin', 'TowerScheduleState', 'TowerAnalyticsState')
|
||||
__all__ = ('Instance', 'InstanceGroup', 'TowerScheduleState', 'TowerAnalyticsState')
|
||||
|
||||
|
||||
class HasPolicyEditsMixin(HasEditsMixin):
|
||||
@ -266,24 +263,6 @@ class TowerAnalyticsState(SingletonModel):
|
||||
last_run = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
||||
class JobOrigin(models.Model):
|
||||
"""A model representing the relationship between a unified job and
|
||||
the instance that was responsible for starting that job.
|
||||
|
||||
It may be possible that a job has no origin (the common reason for this
|
||||
being that the job was started on Tower < 2.1 before origins were a thing).
|
||||
This is fine, and code should be able to handle it. A job with no origin
|
||||
is always assumed to *not* have the current instance as its origin.
|
||||
"""
|
||||
unified_job = models.OneToOneField(UnifiedJob, related_name='job_origin', on_delete=models.CASCADE)
|
||||
instance = models.ForeignKey(Instance, on_delete=models.CASCADE)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
app_label = 'main'
|
||||
|
||||
|
||||
def schedule_policy_task():
|
||||
from awx.main.tasks import apply_cluster_membership_policies
|
||||
connection.on_commit(lambda: apply_cluster_membership_policies.apply_async())
|
||||
@ -311,31 +290,6 @@ def on_instance_deleted(sender, instance, using, **kwargs):
|
||||
schedule_policy_task()
|
||||
|
||||
|
||||
# Unfortunately, the signal can't just be connected against UnifiedJob; it
|
||||
# turns out that creating a model's subclass doesn't fire the signal for the
|
||||
# superclass model.
|
||||
@receiver(post_save, sender=InventoryUpdate)
|
||||
@receiver(post_save, sender=Job)
|
||||
@receiver(post_save, sender=ProjectUpdate)
|
||||
def on_job_create(sender, instance, created=False, raw=False, **kwargs):
|
||||
"""When a new job is created, save a record of its origin (the machine
|
||||
that started the job).
|
||||
"""
|
||||
# Sanity check: We only want to create a JobOrigin record in cases where
|
||||
# we are making a new record, and in normal situations.
|
||||
#
|
||||
# In other situations, we simply do nothing.
|
||||
if raw or not created:
|
||||
return
|
||||
|
||||
# Create the JobOrigin record, which attaches to the current instance
|
||||
# (which started the job).
|
||||
job_origin, new = JobOrigin.objects.get_or_create(
|
||||
instance=Instance.objects.me(),
|
||||
unified_job=instance,
|
||||
)
|
||||
|
||||
|
||||
class UnifiedJobTemplateInstanceGroupMembership(models.Model):
|
||||
|
||||
unifiedjobtemplate = models.ForeignKey(
|
||||
|
@ -277,3 +277,22 @@ def test_saved_passwords_hidden_activity(workflow_job_template, job_template_wit
|
||||
changes = json.loads(entry.changes)
|
||||
assert 'survey_passwords' not in changes
|
||||
assert json.loads(changes['extra_data'])['bbbb'] == '$encrypted$'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_cluster_node_recorded(inventory, project):
|
||||
jt = JobTemplate.objects.create(name='testjt', inventory=inventory, project=project)
|
||||
with mock.patch('awx.main.models.activity_stream.settings.CLUSTER_HOST_ID', 'foo_host'):
|
||||
job = jt.create_unified_job()
|
||||
entry = ActivityStream.objects.filter(job=job).first()
|
||||
assert entry.action_node == 'foo_host'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_cluster_node_long_node_name(inventory, project):
|
||||
jt = JobTemplate.objects.create(name='testjt', inventory=inventory, project=project)
|
||||
with mock.patch('awx.main.models.activity_stream.settings.CLUSTER_HOST_ID', 'f' * 700):
|
||||
job = jt.create_unified_job()
|
||||
# node name is very long, we just want to make sure it does not error
|
||||
entry = ActivityStream.objects.filter(job=job).first()
|
||||
assert entry.action_node.startswith('ffffff')
|
||||
|
Loading…
Reference in New Issue
Block a user