Merge pull request #276 from chrismeyersfsu/fix-fact_inventory_relationship

associate scan runs with a particular inventory host
This commit is contained in:
Chris Meyers
2015-06-11 20:55:13 -04:00
8 changed files with 51 additions and 33 deletions

View File

@@ -2,7 +2,7 @@
# All Rights Reserved
from mongoengine.base import BaseField
from mongoengine import Document, DateTimeField, ReferenceField, StringField
from mongoengine import Document, DateTimeField, ReferenceField, StringField, IntField
from awx.fact.utils.dbtransform import KeyTransform
key_transform = KeyTransform([('.', '\uff0E'), ('$', '\uff04')])
@@ -22,22 +22,17 @@ class TransformField(BaseField):
class FactHost(Document):
hostname = StringField(max_length=100, required=True, unique=True)
inventory_id = IntField(required=True)
# TODO: Consider using hashed index on hostname. django-mongo may not support this but
# executing raw js will
meta = {
'indexes': [
'hostname'
'hostname',
'inventory_id'
]
}
@staticmethod
def get_host_id(hostname):
host = FactHost.objects.get(hostname=hostname)
if host:
return host.id
return None
class Fact(Document):
timestamp = DateTimeField(required=True)
host = ReferenceField(FactHost, required=True)
@@ -49,7 +44,7 @@ class Fact(Document):
meta = {
'indexes': [
'-timestamp',
'host'
'host',
]
}
@@ -65,9 +60,9 @@ class Fact(Document):
# If module not specified then filter query may return more than 1 result.
# Thus, the resulting facts must somehow be unioned/concated/ or kept as an array.
@staticmethod
def get_host_version(hostname, timestamp, module):
def get_host_version(hostname, inventory_id, timestamp, module):
try:
host = FactHost.objects.get(hostname=hostname)
host = FactHost.objects.get(hostname=hostname, inventory_id=inventory_id)
except FactHost.DoesNotExist:
return None
@@ -86,9 +81,9 @@ class Fact(Document):
return None
@staticmethod
def get_host_timeline(hostname, module):
def get_host_timeline(hostname, inventory_id, module):
try:
host = FactHost.objects.get(hostname=hostname)
host = FactHost.objects.get(hostname=hostname, inventory_id=inventory_id)
except FactHost.DoesNotExist:
return None
@@ -99,6 +94,7 @@ class Fact(Document):
return FactVersion.objects.filter(**kv).order_by("-timestamp").values_list('timestamp')
# FIXME: single facts no longer works with the addition of the inventory_id field to the FactHost document
@staticmethod
def get_single_facts(hostnames, fact_key, fact_value, timestamp, module):
kv = {

View File

@@ -93,11 +93,13 @@ class BaseFactTestMixin(MongoDBRequired):
class BaseFactTest(BaseFactTestMixin, MongoDBRequired):
pass
# TODO: for now, we relate all hosts to a single inventory
class FactScanBuilder(object):
def __init__(self):
self.facts_data = {}
self.hostname_data = []
self.inventory_id = 1
self.host_objs = []
self.fact_objs = []
@@ -124,7 +126,7 @@ class FactScanBuilder(object):
if len(self.hostname_data) == 0:
self.hostname_data = ['hostname_%s' % i for i in range(0, host_count)]
self.host_objs = [FactHost(hostname=hostname).save() for hostname in self.hostname_data]
self.host_objs = [FactHost(hostname=hostname, inventory_id=self.inventory_id).save() for hostname in self.hostname_data]
for i in range(0, scan_count):
scan = {}
@@ -186,6 +188,12 @@ class FactScanBuilder(object):
return [self.host_objs[i].hostname for i in range(index_start, index_end)]
def get_inventory_id(self):
return self.inventory_id
def set_inventory_id(self, inventory_id):
self.inventory_id = inventory_id
def get_host(self, index):
return self.host_objs[index]

View File

@@ -16,19 +16,20 @@ __all__ = ['FactHostTest', 'FactTest', 'FactGetHostVersionTest', 'FactGetHostTim
class FactHostTest(BaseFactTest):
def test_create_host(self):
host = FactHost(hostname='hosty')
host = FactHost(hostname='hosty', inventory_id=1)
host.save()
host = FactHost.objects.get(hostname='hosty')
host = FactHost.objects.get(hostname='hosty', inventory_id=1)
self.assertIsNotNone(host, "Host added but not found")
self.assertEqual('hosty', host.hostname, "Gotten record hostname does not match expected hostname")
self.assertEqual(1, host.inventory_id, "Gotten record inventory_id does not match expected inventory_id")
# Ensure an error is raised for .get() that doesn't match a record.
def test_get_host_id_no_result(self):
host = FactHost(hostname='hosty')
host = FactHost(hostname='hosty', inventory_id=1)
host.save()
self.assertRaises(FactHost.DoesNotExist, FactHost.objects.get, hostname='doesnotexist')
self.assertRaises(FactHost.DoesNotExist, FactHost.objects.get, hostname='doesnotexist', inventory_id=1)
class FactTest(BaseFactTest):
def setUp(self):
@@ -36,7 +37,7 @@ class FactTest(BaseFactTest):
def test_add_fact(self):
timestamp = now().replace(microsecond=0)
host = FactHost(hostname="hosty").save()
host = FactHost(hostname="hosty", inventory_id=1).save()
(f_obj, v_obj) = Fact.add_fact(host=host, timestamp=timestamp, module='packages', fact=TEST_FACT_PACKAGES)
f = Fact.objects.get(id=f_obj.id)
v = FactVersion.objects.get(id=v_obj.id)
@@ -65,20 +66,20 @@ class FactGetHostVersionTest(BaseFactTest):
def test_get_host_version_exact_timestamp(self):
fact_known = self.builder.get_scan(0, 'packages')[0]
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), timestamp=self.builder.get_timestamp(0), module='packages')
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=self.builder.get_timestamp(0), module='packages')
self.assertIsNotNone(fact)
self.assertEqual(fact_known, fact)
def test_get_host_version_lte_timestamp(self):
timestamp = self.builder.get_timestamp(0) + relativedelta(days=1)
fact_known = self.builder.get_scan(0, 'packages')[0]
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), timestamp=timestamp, module='packages')
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=timestamp, module='packages')
self.assertIsNotNone(fact)
self.assertEqual(fact_known, fact)
def test_get_host_version_none(self):
timestamp = self.builder.get_timestamp(0) - relativedelta(years=20)
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), timestamp=timestamp, module='packages')
fact = Fact.get_host_version(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), timestamp=timestamp, module='packages')
self.assertIsNone(fact)
class FactGetHostTimelineTest(BaseFactTest):
@@ -89,7 +90,7 @@ class FactGetHostTimelineTest(BaseFactTest):
self.builder.build(scan_count=20, host_count=1)
def test_get_host_timeline_ok(self):
timestamps = Fact.get_host_timeline(hostname=self.builder.get_hostname(0), module='packages')
timestamps = Fact.get_host_timeline(hostname=self.builder.get_hostname(0), inventory_id=self.builder.get_inventory_id(), module='packages')
self.assertIsNotNone(timestamps)
self.assertEqual(len(timestamps), self.builder.get_scan_count())
for i in range(0, self.builder.get_scan_count()):

View File

@@ -62,12 +62,12 @@ class FactTransformTest(BaseFactTest):
self.timestamp = datetime.now().replace(microsecond=0)
def setup_create_fact_dot(self):
self.host = FactHost(hostname='hosty').save()
self.host = FactHost(hostname='hosty', inventory_id=1).save()
self.f = Fact(timestamp=self.timestamp, module='packages', fact=TEST_FACT_PACKAGES_WITH_DOTS, host=self.host)
self.f.save()
def setup_create_fact_dollar(self):
self.host = FactHost(hostname='hosty').save()
self.host = FactHost(hostname='hosty', inventory_id=1).save()
self.f = Fact(timestamp=self.timestamp, module='packages', fact=TEST_FACT_PACKAGES_WITH_DOLLARS, host=self.host)
self.f.save()
@@ -85,7 +85,7 @@ class FactTransformTest(BaseFactTest):
def test_fact_with_dot_serialized_pymongo(self):
#self.setup_create_fact_dot()
host = FactHost(hostname='hosty').save()
host = FactHost(hostname='hosty', inventory_id=1).save()
f = self.db['fact'].insert({
'hostname': 'hosty',
'fact': TEST_FACT_PACKAGES_WITH_DOTS,