Repository: nautobot/nautobot

Issue:
Migration ipam.0022 fails when specific duplicate IPAM objects are present
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Nautobot version (Docker tag too if applicable): v2.1.6b1
* Python version: 
* Database platform, version: PG16
* Middleware(s):

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
### Steps to Reproduce
1. In 1.6, using the same prefix and prefix length, create an aggregate, a prefix in the Global VRF and a prefix in another VRF
2. Upgrade to any version of 2.x and run `nautobot-server migrate`


<!-- What did you expect to happen? -->
### Expected Behavior
Migrations succeed

<!-- What happened instead? -->
### Observed Behavior
Migrations fail on ipam.0022

```
  Applying ipam.0022_aggregate_to_prefix_data_migration...Traceback (most recent call last):
  File "/usr/local/bin/nautobot-server", line 6, in <module>
    sys.exit(main())
  File "/source/nautobot/core/cli/__init__.py", line 52, in main
    run_app(
  File "/source/nautobot/core/runner/runner.py", line 297, 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 244, in handle
    post_migrate_state = executor.migrate(
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/migration.py", line 126, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/usr/local/lib/python3.10/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
    self.code(from_state.apps, schema_editor)
  File "/source/nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py", line 161, in migrate_aggregate_to_prefix
    prefix = Prefix.objects.get(network=instance.network, prefix_length=instance.prefix_length)
  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 439, in get
    raise self.model.MultipleObjectsReturned(
__fake__.Prefix.MultipleObjectsReturned: get() returned more than one Prefix -- it returned 2!
```


Discussion:

Resolving patch:
diff --git a/nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py b/nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py
--- a/nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py
+++ b/nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py
@@ -158,7 +158,11 @@ def migrate_aggregate_to_prefix(apps, schema_editor):
             prefix_length=instance.prefix_length,
             vrf__isnull=True,
         ).exists():
-            prefix = Prefix.objects.get(network=instance.network, prefix_length=instance.prefix_length)
+            prefix = Prefix.objects.filter(
+                network=instance.network,
+                prefix_length=instance.prefix_length,
+                vrf__isnull=True,
+            ).first()
             mismatches.update(_migrate_aggregate_to_existing_prefix(instance, prefix))
 
         else:


Test patch: