Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0: Registering new Job from plugin cannot be done from jobs.py #4005

Closed
jakubkrysl opened this issue Jun 27, 2023 · 4 comments · Fixed by #4009
Closed

2.0: Registering new Job from plugin cannot be done from jobs.py #4005

jakubkrysl opened this issue Jun 27, 2023 · 4 comments · Fixed by #4009
Assignees
Labels
type: bug Something isn't working as expected
Milestone

Comments

@jakubkrysl
Copy link

jakubkrysl commented Jun 27, 2023

Environment

  • Nautobot version (Docker tag too if applicable): 2.0.0-beta.1
  • Python version: 3.10.11
  • Database platform, version:
  • Middleware(s):

Steps to Reproduce

  1. Create a new Job in plugin with read_only = True
  2. make sure the Job is not in DB yet (its 1st registration)
  3. use nautobot.core.celery.register_jobs to register it from jobs.py

Expected Behavior

Job registered and working

Observed Behavior

Job does not exist

  No migrations to apply.
[2023-06-27 20:00:39,562] DEBUG nautobot.core.celery: Importing system Jobs
[2023-06-27 20:00:39,639] INFO nautobot.extras.utils: Refreshed Job "System Jobs: Git Repository: Sync" from <GitRepositorySync>
[2023-06-27 20:00:39,656] INFO nautobot.extras.utils: Refreshed Job "System Jobs: Git Repository: Dry-Run" from <GitRepositoryDryRun>
[2023-06-27 20:00:39,671] INFO nautobot.extras.utils: Refreshed Job "User: Export owner changes" from <ExportOwnerChanges>
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 581, in get_or_create
    return self.get(**kwargs), False
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 435, in get
    raise self.model.DoesNotExist(
__fake__.Job.DoesNotExist: Job matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/bin/nautobot-server", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.10/site-packages/nautobot/core/cli/__init__.py", line 54, in main
    run_app(
  File "/usr/local/lib/python3.10/site-packages/nautobot/core/runner/runner.py", line 263, in run_app
    management.execute_from_command_line([runner_name, command] + command_args)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 89, in wrapped
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 268, in handle
    emit_post_migrate_signal(
  File "/usr/local/lib/python3.10/site-packages/django/core/management/sql.py", line 42, in emit_post_migrate_signal
    models.signals.post_migrate.send(
  File "/usr/local/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 180, in send
    return [
  File "/usr/local/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 181, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/usr/local/lib/python3.10/site-packages/nautobot/core/apps/__init__.py", line 564, in post_migrate_send_nautobot_database_ready
    nautobot_database_ready.send(sender=app_conf, app_config=app_conf, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 180, in send
    return [
  File "/usr/local/lib/python3.10/site-packages/django/dispatch/dispatcher.py", line 181, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/usr/local/lib/python3.10/site-packages/nautobot/extras/signals.py", line 257, in refresh_job_models
    job_model, _ = refresh_job_model_from_job_class(Job, task.__class__)
  File "/usr/local/lib/python3.10/site-packages/nautobot/extras/utils.py", line 412, in refresh_job_model_from_job_class
    job_model, created = job_model_class.objects.get_or_create(
  File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 588, in get_or_create
    return self.create(**params), True
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 453, in create
    obj.save(force_insert=True, using=self.db)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 739, in save
    self.save_base(using=using, force_insert=force_insert,
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 776, in save_base
    updated = self._save_table(
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 881, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 919, in _do_insert
    return manager._insert(
  File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1415, in execute_sql
    for sql, params in self.as_sql():
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1358, in as_sql
    value_rows = [
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1359, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1359, in <listcomp>
    [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1300, in prepare_value
    value = field.get_db_prep_save(value, connection=self.connection)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 842, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 837, in get_db_prep_value
    value = self.get_prep_value(value)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 986, in get_prep_value
    return self.to_python(value)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 976, in to_python
    raise exceptions.ValidationError(
django.core.exceptions.ValidationError: ['“(True,)” value must be either True or False.']

Additional context

If I follow current docs and register the Job in __init__.py, it works but I cannot directly import anything from Nautobot and have to use django,apps for any imports. Based on Slack discussion this is not the desired behavior and registering in jobs.py should be the way to go.
If the Job is already present in DB, registering in jobs.py works flawlessly, so 2nd step in reproducer is needed.

@glennmatthews
Copy link
Contributor

Thanks for the report! I suspect that, in addition to whatever's actually causing the ValidationError to be raised, our Job.objects.get_or_create() call from refresh_job_model_from_job_class() needs to add some graceful handling for errors such as this.

@glennmatthews glennmatthews added the type: bug Something isn't working as expected label Jun 27, 2023
@glennmatthews glennmatthews added this to the v2.0.0 milestone Jun 27, 2023
@glennmatthews
Copy link
Contributor

I can reproduce the issue by incorrectly specifying the read_only variable, i.e.:

class ExampleJob(Job):
    class Meta:
        read_only = True,

@glennmatthews glennmatthews self-assigned this Jun 27, 2023
@jakubkrysl
Copy link
Author

I can reproduce the issue by incorrectly specifying the read_only variable, i.e.:

class ExampleJob(Job):
    class Meta:
        read_only = True,

Futher testing confirms this. I have another Job that was only imported and no loaded as it was failing on the 1st registered and this was 3rd, so for testing purposes I left only the 1st Job to be registered.
The 3rd Job had it like this for some reason:

class ExmpleJob(Job):
    class Meta:
        read_only = (True, )

@glennmatthews
Copy link
Contributor

Fixed by #4009.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug Something isn't working as expected
Projects
No open projects
Archived in project
2 participants