nautobot / nautobot-app-ssot

Single Source of Truth for Nautobot
https://docs.nautobot.com/projects/ssot/en/latest/
Other
36 stars 34 forks source link

AttributeError: Manager isn't accessible via ContentType instances #380

Closed gneville-ot closed 6 months ago

gneville-ot commented 6 months ago

Environment

Expected Behavior

Cables are created

Observed Behavior

This was working with SSoT version 2.2.0 but doesn't work with 2.3.0.

A traceback is produced and cables aren't created:

  File "/usr/local/lib/python3.11/site-packages/celery/app/trace.py", line 477, in trace_task
    R = retval = fun(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/nautobot/extras/jobs.py", line 153, in __call__
    return self.run(*args, **deserialized_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/git/dcim_data_ssot/jobs/yaml_sync_job.py", line 4834, in run
    super().run(dryrun=self.dryrun, memory_profiling=self.memory_profiling, *args, **kwargs)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/jobs/base.py", line 316, in run
    self.sync_data(memory_profiling)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/jobs/base.py", line 165, in sync_data
    self.execute_sync()
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/jobs/base.py", line 97, in execute_sync
    self.source_adapter.sync_to(self.target_adapter, flags=self.diffsync_flags)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/diffsync/__init__.py", line 601, in sync_to
    return target.sync_from(self, diff_class=diff_class, flags=flags, callback=callback, diff=diff)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/diffsync/__init__.py", line 573, in sync_from
    result = syncer.perform_sync()
             ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/diffsync/helpers.py", line 329, in perform_sync
    changed |= self.sync_diff_element(element)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/diffsync/helpers.py", line 379, in sync_diff_element
    changed, modified_model = self.sync_model(src_model=src_model, dst_model=dst_model, ids=ids, attrs=attrs)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/diffsync/helpers.py", line 428, in sync_model
    dst_model = self.model_class.create(diffsync=self.dst_diffsync, ids=ids, attrs=attrs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/contrib.py", line 539, in create
    cls._update_obj_with_parameters(obj, parameters, diffsync)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/contrib.py", line 641, in _update_obj_with_parameters
    cls._lookup_and_set_foreign_keys(relationship_fields["foreign_keys"], obj, diffsync=diffsync)
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/contrib.py", line 779, in _lookup_and_set_foreign_keys
    related_object = diffsync.get_from_orm_cache(related_model_dict, related_model)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/contrib.py", line 149, in get_from_orm_cache
    self._cache[model_cache_key][parameter_set] = model_class.objects.get(**dict(parameter_set))
                                                  ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 179, in __get__
    raise AttributeError("Manager isn't accessible via %s instances" % cls.__name__)
AttributeError: Manager isn't accessible via ContentType instances

Steps to Reproduce

  1. Create two devices
  2. Attempt to create a cable connection between the devices using SSoT

Example:

        obj = self.cable(
            termination_a__device__name="device1",
            termination_a__name="PSU0",
            termination_a__app_label="dcim",
            termination_a__model="powerport",
            termination_b__device__name="device2",
            termination_b__name="1",
            termination_b__app_label="dcim",
            termination_b__model="poweroutlet",
            type="power",
            status__name="Connected",
        )
        self.add(obj)
class CableModel(NautobotModel):
    """Shared data model representing a Cable."""

    # Metadata about this model
    _model = Cable
    _modelname = "cable"
    _identifiers = (
        "termination_a__device__name",
        "termination_a__name",
        "termination_a__app_label",
        "termination_a__model",
        "termination_b__device__name",
        "termination_b__name",
        "termination_b__app_label",
        "termination_b__model",
    )
    _attributes = (
        "type",
        "status__name",
    )
    _children = {}

    termination_a__device__name: str
    termination_a__name: str
    termination_a__app_label: str
    termination_a__model: str
    termination_b__device__name: str
    termination_b__name: str
    termination_b__app_label: str
    termination_b__model: str
    type: str
    status__name: str
Kircheneer commented 6 months ago

Reproduced here: https://github.com/Kircheneer/nautobot-plugin-ssot/tree/fix/%23380

Kircheneer commented 6 months ago

Fixed in #388. Thanks for the report!