Skip to content

Commit

Permalink
feat: new mgmt command to validate default enrollment intentions
Browse files Browse the repository at this point in the history
Introduced validate_default_enrollment_intentions.py to check that all
DefaultEnterpriseEnrollmentIntention objects have a valid content_key
which actually belongs to at least one of the related customer's
catalogs.

ENT-9941
  • Loading branch information
pwnage101 committed Jan 25, 2025
1 parent d5f5cb9 commit bbc1cee
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""
Django management command to validate that DefaultEnterpriseEnrollmentIntention
objects have enrollable content.
"""
import logging
from datetime import datetime, timedelta

Check warning on line 6 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L5-L6

Added lines #L5 - L6 were not covered by tests

from django.core.management import BaseCommand, CommandError
from django.db.models import Max
from django.db.models.functions import Greatest

Check warning on line 10 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L8-L10

Added lines #L8 - L10 were not covered by tests

from enterprise.api_client.enterprise_catalog import EnterpriseCatalogApiClient
from enterprise.models import EnterpriseCustomer

Check warning on line 13 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L12-L13

Added lines #L12 - L13 were not covered by tests

logger = logging.getLogger(__name__)

Check warning on line 15 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L15

Added line #L15 was not covered by tests


class Command(BaseCommand):

Check warning on line 18 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L18

Added line #L18 was not covered by tests
"""
Enumerate the catalog filters and log information about how we might migrate them.
"""

def __init__(self, *args, **kwargs):
self.enterprise_catalog_client = None
self.delay_minutes = None
super().__init__(*args, **kwargs)

Check warning on line 26 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L23-L26

Added lines #L23 - L26 were not covered by tests

def add_arguments(self, parser):
parser.add_argument(

Check warning on line 29 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L28-L29

Added lines #L28 - L29 were not covered by tests
'--delay-minutes',
dest='delay_minutes',
required=False,
type=int,
default=30,
help="How long after a customer's catalog has been updated are we allowed to evaluate the customer."
)

@property
def latest_change_allowed(self):
return datetime.now() - timedelta(minutes=self.delay_minutes)

Check warning on line 40 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L38-L40

Added lines #L38 - L40 were not covered by tests

def handle_default_enrollment_intention(self, customer, intention):

Check warning on line 42 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L42

Added line #L42 was not covered by tests
"""
Check that the default enrollment intention's content_key is contained in any of the customer's catalogs.
Returns:
bool: True if the default enrollment intention is valid.
"""
content_metadata = self.enterprise_catalog_client.get_customer_content_metadata_content_identifier(

Check warning on line 49 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L49

Added line #L49 was not covered by tests
customer.uuid,
intention.content_key,
)
contained_in_customer_catalogs = bool(content_metadata)

Check warning on line 53 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L53

Added line #L53 was not covered by tests
if contained_in_customer_catalogs:
logger.info(

Check warning on line 55 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L55

Added line #L55 was not covered by tests
f"handle_default_enrollment_intention(): Default enrollment intention {intention} "
"is compatible with the customer's catalogs."
)
else:
logger.error(

Check warning on line 60 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L60

Added line #L60 was not covered by tests
f"handle_default_enrollment_intention(): Default enrollment intention {intention} "
"is NOT compatible with the customer's catalogs."
)
return contained_in_customer_catalogs

Check warning on line 64 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L64

Added line #L64 was not covered by tests

def handle_customer(self, customer):

Check warning on line 66 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L66

Added line #L66 was not covered by tests
"""
Try to evaluate an EnterpriseCustomer for any invalid DefaultEnterpriseEnrollmentIntention records.
Returns:
dict: A structured result object that indicates whether the
customer was skipped, and which intentions are invalid.
"""
result = {

Check warning on line 74 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L74

Added line #L74 was not covered by tests
'skipped': None,
'invalid_intentions': None,
}
if customer.catalogs_modified_latest > self.latest_change_allowed:
result['skipped'] = True
logger.info(

Check warning on line 80 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L79-L80

Added lines #L79 - L80 were not covered by tests
f"handle_customer(): SKIPPING Evaluating default enrollment intentions for customer {customer}."
)
return result
result['skipped'] = False
logger.info(f"handle_customer(): Evaluating default enrollment intentions for customer {customer}.")
results = {

Check warning on line 86 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L83-L86

Added lines #L83 - L86 were not covered by tests
intention: self.handle_default_enrollment_intention(customer, intention)
for intention in customer.default_enrollment_intentions
}
result['invalid_intentions'] = [intention for intention, valid in results.items() if not valid]
return result

Check warning on line 91 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L90-L91

Added lines #L90 - L91 were not covered by tests

def handle(self, *args, **options):
self.enterprise_catalog_client = EnterpriseCatalogApiClient()
self.delay_minutes = options.get("delay_minutes")

Check warning on line 95 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L93-L95

Added lines #L93 - L95 were not covered by tests

customers = EnterpriseCustomer.objects.annotate(

Check warning on line 97 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L97

Added line #L97 was not covered by tests
catalogs_modified_latest=Greatest(
Max("enterprise_customer_catalogs__modified"),
Max("enterprise_customer_catalogs__enterprise_catalog_query__modified"),
),
).prefetch_related(
"default_enrollment_intentions",
)

results = {customer: self.handle_customer(customer) for customer in customers}
results_evaluated = {customer: result for customer, result in results.items() if not result['skipped']}
results_failed = {

Check warning on line 108 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L106-L108

Added lines #L106 - L108 were not covered by tests
customer: result
for customer, result in results_evaluated.items()
if result['invalid_intentions']}
invalid_intentions = [

Check warning on line 112 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L112

Added line #L112 was not covered by tests
intention
for intention in failed_result['invalid_intentions']
for failed_result in results_failed.values()
]

count_customers_total = len(results)
count_customers_evaluated = len(results_evaluated)
count_customers_skipped = count_customers_total - count_customers_evaluated
count_customers_failed = len(results_failed)
count_customers_passed = count_customers_evaluated - count_customers_failed

Check warning on line 122 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L118-L122

Added lines #L118 - L122 were not covered by tests

logger.info(

Check warning on line 124 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L124

Added line #L124 was not covered by tests
f"{count_customers_total} total customers found, "
f"and {count_customers_evaluated}/{count_customers_total} customers were evaluated "
f"({count_customers_skipped}/{count_customers_total} skipped)."
)
logger.info(

Check warning on line 129 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L129

Added line #L129 was not covered by tests
f"Out of {count_customers_evaluated} total evaluated customers, "
f"{count_customers_passed}/{count_customers_evaluated} customers passed validation "
f"({count_customers_failed}/{count_customers_evaluated} failed)."
)
if count_customers_failed:
logger.error("Summary of all {len(invalid_intentions)} invalid intentions: {invalid_intentions}")
logger.error("FAILURE: Some default enrollment intentions were invalid.")
raise CommandError(

Check warning on line 137 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L135-L137

Added lines #L135 - L137 were not covered by tests
f"{len(invalid_intentions)} invalid default enrollment intentions found "
f"across {count_customers_failed} customers."
)
logger.info("SUCCESS: All default enrollment intentions are valid!")

Check warning on line 141 in enterprise/management/commands/validate_default_enrollment_intentions.py

View check run for this annotation

Codecov / codecov/patch

enterprise/management/commands/validate_default_enrollment_intentions.py#L141

Added line #L141 was not covered by tests
9 changes: 9 additions & 0 deletions enterprise/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2726,6 +2726,15 @@ def save(self, *args, **kwargs):
# Call the superclass save method
super().save(*args, **kwargs)

def __str__(self):
"""
Return human-readable string representation.
"""
return (
f"<DefaultEnterpriseEnrollmentIntention for customer={self.enterprise_customer.uuid} "
f"and content_key={self.content_key}>"
)


class DefaultEnterpriseEnrollmentRealization(TimeStampedModel):
"""
Expand Down

0 comments on commit bbc1cee

Please sign in to comment.