Clean up migrations

This commit is contained in:
Jeremy Stretch 2024-02-22 15:27:38 -05:00
parent 274bbfa22f
commit 890c94bcc9
4 changed files with 83 additions and 72 deletions

View File

@ -1,12 +1,10 @@
# Generated by Django 4.2.9 on 2024-02-05 21:37
import inspect import inspect
import os import os
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
from importlib.machinery import SourceFileLoader from importlib.machinery import SourceFileLoader
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
# #
# Note: This has a couple dependencies on the codebase if doing future modifications: # Note: This has a couple dependencies on the codebase if doing future modifications:
@ -14,104 +12,117 @@ from importlib.machinery import SourceFileLoader
# settings.SCRIPTS_ROOT and settings.REPORTS_ROOT to be in settings # settings.SCRIPTS_ROOT and settings.REPORTS_ROOT to be in settings
# #
def update_event_rules(apps, schema_editor): ROOT_PATHS = {
Script = apps.get_model('extras', 'Script') 'scripts': settings.SCRIPTS_ROOT,
ContentType = apps.get_model('contenttypes', 'ContentType') 'reports': settings.REPORTS_ROOT,
ct = ContentType.objects.filter(app_label='extras', model='script').first() }
EventRule = apps.get_model('extras', 'EventRule')
ct_script_module = ContentType.objects.filter(app_label='extras', model='scriptmodule').first()
for rule in EventRule.objects.filter(action_object_type=ct_script_module):
name = rule.action_parameters.get('script_name')
obj, created = Script.objects.get_or_create(
module_id=rule.action_object_id,
name=name,
defaults={'is_valid': False}
)
rule.action_object_type = ct
rule.action_object_id = obj.id
rule.save()
def full_path(instance): def get_full_path(scriptmodule):
root_path = { """
'scripts': settings.SCRIPTS_ROOT, Return the full path to a ScriptModule's file on disk.
'reports': settings.REPORTS_ROOT, """
}[instance.file_root] root_path = ROOT_PATHS[scriptmodule.file_root]
return os.path.join(root_path, instance.file_path) return os.path.join(root_path, scriptmodule.file_path)
def python_name(instance): def get_python_name(scriptmodule):
path, filename = os.path.split(full_path(instance)) """
name = os.path.splitext(filename)[0] Return the Python name of a ScriptModule's file on disk.
if name == '__init__': """
# File is a package path, filename = os.path.split(scriptmodule.file_path)
return os.path.basename(path) return os.path.splitext(filename)[0]
else:
return name
def is_script(obj): def is_script(obj):
"""
Returns True if the passed Python object is a Script or Report.
"""
from extras.scripts import Script from extras.scripts import Script
from extras.reports import Report from extras.reports import Report
try: try:
return (issubclass(obj, Report) and obj != Report) or (issubclass(obj, Script) and obj != Script) if issubclass(obj, Report) and obj != Report:
return True
if issubclass(obj, Script) and obj != Script:
return True
except TypeError: except TypeError:
return False pass
return False
def get_python_module(instance): def get_module_scripts(scriptmodule):
loader = SourceFileLoader(python_name(instance), full_path(instance)) """
module = loader.load_module() Return a dictionary mapping of name and script class inside the passed ScriptModule.
return module """
def get_name(cls):
def get_module_scripts(apps, instance):
def _get_name(cls):
# For child objects in submodules use the full import path w/o the root module as the name # For child objects in submodules use the full import path w/o the root module as the name
return cls.full_name.split(".", maxsplit=1)[1] return cls.full_name.split(".", maxsplit=1)[1]
try: loader = SourceFileLoader(get_python_name(scriptmodule), get_full_path(scriptmodule))
module = get_python_module(instance) module = loader.load_module()
except Exception as e:
module = None
return
scripts = {} scripts = {}
ordered = getattr(module, 'script_order', []) ordered = getattr(module, 'script_order', [])
for cls in ordered: for cls in ordered:
scripts[_get_name(cls)] = cls scripts[get_name(cls)] = cls
for name, cls in inspect.getmembers(module, is_script): for name, cls in inspect.getmembers(module, is_script):
if cls not in ordered: if cls not in ordered:
scripts[_get_name(cls)] = cls scripts[get_name(cls)] = cls
return scripts return scripts
def update_scripts(apps, schema_editor): def update_scripts(apps, schema_editor):
ScriptModule = apps.get_model('extras', 'ScriptModule') """
Script = apps.get_model('extras', 'Script') Create a new Script object for each script inside each existing ScriptModule, and update any related jobs to
reference the new Script object.
"""
ContentType = apps.get_model('contenttypes', 'ContentType') ContentType = apps.get_model('contenttypes', 'ContentType')
Script = apps.get_model('extras', 'Script')
ScriptModule = apps.get_model('extras', 'ScriptModule')
Job = apps.get_model('core', 'Job') Job = apps.get_model('core', 'Job')
ct = ContentType.objects.filter(app_label='extras', model='script').first()
ct_module = ContentType.objects.filter(app_label='extras', model='scriptmodule').first() script_ct = ContentType.objects.get_for_model(Script)
scriptmodule_ct = ContentType.objects.get_for_model(ScriptModule)
for module in ScriptModule.objects.all(): for module in ScriptModule.objects.all():
module_scripts = get_module_scripts(apps, module) for script_name in get_module_scripts(module):
if module_scripts: script = Script.objects.create(
for script in module_scripts.keys(): name=script_name,
obj = Script.objects.create( module=module,
name=script, )
module=ScriptModule.objects.get(file_root=module.file_root, file_path=module.file_path),
)
# update all jobs associated with this module/name to point to the new script obj # Update all Jobs associated with this ScriptModule & script name to point to the new Script object
if ct: Job.objects.filter(
Job.objects.filter(object_type=ct_module, object_id=module.id, name=script).update(object_type=ct, object_id=obj.id) object_type=scriptmodule_ct,
object_id=module.pk,
name=script_name
).update(object_type=script_ct, object_id=script.pk)
def update_event_rules(apps, schema_editor):
"""
Update any existing EventRules for scripts. Change action_object_type from ScriptModule to Script, and populate
the ID of the related Script object.
"""
ContentType = apps.get_model('contenttypes', 'ContentType')
Script = apps.get_model('extras', 'Script')
ScriptModule = apps.get_model('extras', 'ScriptModule')
EventRule = apps.get_model('extras', 'EventRule')
script_ct = ContentType.objects.get_for_model(Script)
scriptmodule_ct = ContentType.objects.get_for_model(ScriptModule)
for eventrule in EventRule.objects.filter(action_object_type=scriptmodule_ct):
name = eventrule.action_parameters.get('script_name')
obj, created = Script.objects.get_or_create(
module_id=eventrule.action_object_id,
name=name,
defaults={'is_executable': False}
)
EventRule.objects.filter(pk=eventrule.pk).update(action_object_type=script_ct, action_object_id=obj.id)
class Migration(migrations.Migration): class Migration(migrations.Migration):

View File

@ -1,12 +1,10 @@
# Generated by Django 4.2.9 on 2024-02-13 23:20
from django.db import migrations from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('extras', '0109_script_models'), ('extras', '0109_script_model'),
] ]
operations = [ operations = [

View File

@ -6,6 +6,7 @@ __all__ = (
) )
# Required by extras/migrations/0109_script_models.py
class Report(BaseScript): class Report(BaseScript):
# #

View File

@ -156,6 +156,7 @@ REMOTE_AUTH_SUPERUSERS = getattr(configuration, 'REMOTE_AUTH_SUPERUSERS', [])
REMOTE_AUTH_STAFF_GROUPS = getattr(configuration, 'REMOTE_AUTH_STAFF_GROUPS', []) REMOTE_AUTH_STAFF_GROUPS = getattr(configuration, 'REMOTE_AUTH_STAFF_GROUPS', [])
REMOTE_AUTH_STAFF_USERS = getattr(configuration, 'REMOTE_AUTH_STAFF_USERS', []) REMOTE_AUTH_STAFF_USERS = getattr(configuration, 'REMOTE_AUTH_STAFF_USERS', [])
REMOTE_AUTH_GROUP_SEPARATOR = getattr(configuration, 'REMOTE_AUTH_GROUP_SEPARATOR', '|') REMOTE_AUTH_GROUP_SEPARATOR = getattr(configuration, 'REMOTE_AUTH_GROUP_SEPARATOR', '|')
# Required by extras/migrations/0109_script_models.py
REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/') REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300) RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300)
RQ_RETRY_INTERVAL = getattr(configuration, 'RQ_RETRY_INTERVAL', 60) RQ_RETRY_INTERVAL = getattr(configuration, 'RQ_RETRY_INTERVAL', 60)