From 98f8faa349f9f650b955efc44a4cddd4337d243c Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Tue, 12 Dec 2017 14:25:58 -0500 Subject: [PATCH] simplify query for active_count --- awx/main/managers.py | 16 ++++++++----- .../tests/functional/models/test_inventory.py | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/awx/main/managers.py b/awx/main/managers.py index 69d4a24b6b..aa478cb027 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -7,7 +7,7 @@ import logging from django.db import models from django.utils.timezone import now -from django.db.models import Sum, Q +from django.db.models import Sum from django.conf import settings from awx.main.utils.filters import SmartFilter @@ -21,11 +21,15 @@ class HostManager(models.Manager): """Custom manager class for Hosts model.""" def active_count(self): - """Return count of active, unique hosts for licensing. Exclude ones source from another Tower""" - try: - return self.filter(~Q(inventory_sources__source='tower')).order_by('name').distinct('name').count() - except NotImplementedError: # For unit tests only, SQLite doesn't support distinct('name') - return len(set(self.values_list('name', flat=True))) + """Return count of active, unique hosts for licensing. + Construction of query involves: + - remove any ordering specified in model's Meta + - Exclude hosts sourced from another Tower + - Restrict the query to only return the name column + - Only consider results that are unique + - Return the count of this query + """ + return self.order_by().exclude(inventory_sources__source='tower').values('name').distinct().count() def get_queryset(self): """When the parent instance of the host query set has a `kind=smart` and a `host_filter` diff --git a/awx/main/tests/functional/models/test_inventory.py b/awx/main/tests/functional/models/test_inventory.py index 35c5a63d4f..7a537e6a2a 100644 --- a/awx/main/tests/functional/models/test_inventory.py +++ b/awx/main/tests/functional/models/test_inventory.py @@ -35,6 +35,30 @@ class TestInventoryScript: } +@pytest.mark.django_db +class TestActiveCount: + + def test_host_active_count(self, organization): + inv1 = Inventory.objects.create(name='inv1', organization=organization) + inv2 = Inventory.objects.create(name='inv2', organization=organization) + assert Host.objects.active_count() == 0 + inv1.hosts.create(name='host1') + inv2.hosts.create(name='host1') + assert Host.objects.active_count() == 1 + inv1.hosts.create(name='host2') + assert Host.objects.active_count() == 2 + + def test_active_count_minus_tower(self, inventory): + inventory.hosts.create(name='locally-managed-host') + source = inventory.inventory_sources.create( + name='tower-source', source='tower' + ) + source.hosts.create( + name='remotely-managed-host', inventory=inventory + ) + assert Host.objects.active_count() == 1 + + @pytest.mark.django_db class TestSCMUpdateFeatures: