add model fact recent

* Copy of the most recent system tracking fact for each module type.
Utimately, this allows us to GIN index the jsonb object to support
fact searching.
This commit is contained in:
Chris Meyers 2017-04-04 16:32:30 -04:00
parent cc476541a1
commit f5d7d0bce5
3 changed files with 96 additions and 2 deletions

View File

@ -5,6 +5,7 @@
import json
import re
import sys
import six
from pyparsing import infixNotation, opAssoc, Optional, Literal, CharsNotIn
# Django
@ -45,6 +46,22 @@ class JSONField(upstream_JSONField):
return {}
return super(JSONField, self).from_db_value(value, expression, connection, context)
class JSONBField(upstream_JSONField):
def get_db_prep_value(self, value, connection, prepared=False):
if connection.vendor == 'sqlite':
# sqlite (which we use for tests) does not support jsonb;
return json.dumps(value)
return super(JSONBField, self).get_db_prep_value(
value, connection, prepared
)
def from_db_value(self, value, expression, connection, context):
# Work around a bug in django-jsonfield
# https://bitbucket.org/schinckel/django-jsonfield/issues/57/cannot-use-in-the-same-project-as-djangos
if isinstance(value, six.string_types):
return json.loads(value)
return value
# Based on AutoOneToOneField from django-annoying:
# https://bitbucket.org/offline/django-annoying/src/a0de8b294db3/annoying/fields.py

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Python
from __future__ import unicode_literals
# Django
from django.db import migrations, models
from psycopg2.extensions import AsIs
# AWX
import awx.main.fields
from awx.main.models import FactRecent
class Migration(migrations.Migration):
dependencies = [
('main', '0036_v311_insights'),
]
operations = [
migrations.CreateModel(
name='FactRecent',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('timestamp', models.DateTimeField(default=None, help_text='Date and time of the corresponding fact scan gathering time.', editable=False)),
('module', models.CharField(max_length=128)),
('facts', awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True)),
('host', models.ForeignKey(related_name='facts_recent', to='main.Host', help_text='Host for the facts that the fact scan captured.')),
],
),
migrations.AlterField(
model_name='fact',
name='facts',
field=awx.main.fields.JSONBField(default={}, help_text='Arbitrary JSON structure of module facts captured at timestamp for a single host.', blank=True),
),
migrations.AlterIndexTogether(
name='factrecent',
index_together=set([('timestamp', 'module', 'host')]),
),
migrations.RunSQL([("CREATE INDEX fact_recent_facts_default_gin ON %s USING gin"
"(facts jsonb_path_ops);", [AsIs(FactRecent._meta.db_table)])]),
]

View File

@ -6,7 +6,39 @@ from django.utils.translation import ugettext_lazy as _
from jsonbfield.fields import JSONField
__all__ = ('Fact', )
from awx.main.fields import JSONBField
__all__ = ('Fact', 'FactRecent')
class FactRecent(models.Model):
host = models.ForeignKey(
'Host',
related_name='facts_recent',
db_index=True,
on_delete=models.CASCADE,
help_text=_('Host for the facts that the fact scan captured.'),
)
timestamp = models.DateTimeField(
default=None,
editable=False,
help_text=_('Date and time of the corresponding fact scan gathering time.')
)
module = models.CharField(max_length=128)
facts = JSONBField(blank=True, default={}, help_text=_('Arbitrary JSON structure of module facts captured at timestamp for a single host.'))
class Meta:
app_label = 'main'
index_together = [
["timestamp", "module", "host"],
]
@staticmethod
def add_fact(host_id, module, timestamp, facts):
qs = FactRecent.objects.filter(host_id=host_id, module=module)
qs.delete()
fact_obj = FactRecent.objects.create(host_id=host_id, module=module, timestamp=timestamp, facts=facts)
return fact_obj
class Fact(models.Model):
@ -26,7 +58,7 @@ class Fact(models.Model):
help_text=_('Date and time of the corresponding fact scan gathering time.')
)
module = models.CharField(max_length=128)
facts = JSONField(blank=True, default={}, help_text=_('Arbitrary JSON structure of module facts captured at timestamp for a single host.'))
facts = JSONBField(blank=True, default={}, help_text=_('Arbitrary JSON structure of module facts captured at timestamp for a single host.'))
class Meta:
app_label = 'main'
@ -60,6 +92,8 @@ class Fact(models.Model):
@staticmethod
def add_fact(host_id, module, timestamp, facts):
FactRecent.add_fact(host_id=host_id, module=module, timestamp=timestamp, facts=facts)
fact_obj = Fact.objects.create(host_id=host_id, module=module, timestamp=timestamp, facts=facts)
fact_obj.save()
return fact_obj