Repository: PrefectHQ/prefect

Issue:
do not create `default-agent-pool` work pool for empty state server
### First check

- [X] I am a contributor to the Prefect codebase

### Description

![image](https://github.com/PrefectHQ/prefect/assets/31014960/1d10b7f5-623a-4e2b-bb6f-db4494a23d5e)


### Impact

misleading to new users as to what our recommended deployment patterns are

### Additional context

this may require some DB migration


Discussion:
we should be able to edit the old data migration directly [here](https://github.com/PrefectHQ/prefect/blob/main/src/prefect/server/database/migrations/versions/postgresql/2023_01_31_110543_f98ae6d8e2cc_work_queue_data_migration.py) (for both sqlite and pg)

Resolving patch:
diff --git a/src/prefect/server/database/migrations/versions/postgresql/2023_01_31_110543_f98ae6d8e2cc_work_queue_data_migration.py b/src/prefect/server/database/migrations/versions/postgresql/2023_01_31_110543_f98ae6d8e2cc_work_queue_data_migration.py
--- a/src/prefect/server/database/migrations/versions/postgresql/2023_01_31_110543_f98ae6d8e2cc_work_queue_data_migration.py
+++ b/src/prefect/server/database/migrations/versions/postgresql/2023_01_31_110543_f98ae6d8e2cc_work_queue_data_migration.py
@@ -29,104 +29,116 @@ def upgrade():
     # Create default agent work pool and associate all existing queues with it
     connection = op.get_bind()
 
-    connection.execute(
-        sa.text(
-            "INSERT INTO work_pool (name, type) VALUES ('default-agent-pool',"
-            " 'prefect-agent')"
-        )
-    )
-
-    default_pool_id = connection.execute(
-        sa.text("SELECT id FROM work_pool WHERE name = 'default-agent-pool'")
+    n_work_queues_without_a_work_pool = connection.execute(
+        sa.text("SELECT COUNT(*) FROM work_queue WHERE work_pool_id IS NULL")
     ).fetchone()[0]
 
-    default_queue = connection.execute(
-        sa.text("SELECT id FROM work_queue WHERE name = 'default'")
-    ).fetchone()
-
-    if not default_queue:
+    if n_work_queues_without_a_work_pool > 0:
         connection.execute(
             sa.text(
-                "INSERT INTO work_queue (name, work_pool_id) VALUES ('default',"
-                " :default_pool_id)"
-            ).params({"default_pool_id": default_pool_id}),
+                "INSERT INTO work_pool (name, type) VALUES ('default-agent-pool',"
+                " 'prefect-agent')"
+            )
         )
 
-    connection.execute(
-        sa.text(
-            "UPDATE work_queue SET work_pool_id = :default_pool_id WHERE work_pool_id"
-            " IS NULL"
-        ).params({"default_pool_id": default_pool_id}),
-    )
-
-    default_queue_id = connection.execute(
-        sa.text(
-            "SELECT id FROM work_queue WHERE name = 'default' and work_pool_id ="
-            " :default_pool_id"
-        ).params({"default_pool_id": default_pool_id}),
-    ).fetchone()[0]
+        default_pool_id = connection.execute(
+            sa.text("SELECT id FROM work_pool WHERE name = 'default-agent-pool'")
+        ).fetchone()[0]
 
-    connection.execute(
-        sa.text(
-            "UPDATE work_pool SET default_queue_id = :default_queue_id WHERE id ="
-            " :default_pool_id"
-        ).params(
-            {"default_pool_id": default_pool_id, "default_queue_id": default_queue_id}
-        ),
-    )
-
-    # Set priority on all queues and update flow runs and deployments
-    queue_rows = connection.execute(
-        sa.text(
-            "SELECT id, name FROM work_queue WHERE work_pool_id = :default_pool_id"
-        ).params({"default_pool_id": default_pool_id}),
-    ).fetchall()
+        default_queue = connection.execute(
+            sa.text("SELECT id FROM work_queue WHERE name = 'default'")
+        ).fetchone()
 
-    with op.get_context().autocommit_block():
-        for enumeration, row in enumerate(queue_rows):
+        if not default_queue:
             connection.execute(
                 sa.text(
-                    "UPDATE work_queue SET priority = :priority WHERE id = :id"
-                ).params({"priority": enumeration + 1, "id": row[0]}),
+                    "INSERT INTO work_queue (name, work_pool_id) VALUES ('default',"
+                    " :default_pool_id)"
+                ).params({"default_pool_id": default_pool_id}),
             )
 
-            batch_size = 250
+        connection.execute(
+            sa.text(
+                "UPDATE work_queue SET work_pool_id = :default_pool_id WHERE work_pool_id"
+                " IS NULL"
+            ).params({"default_pool_id": default_pool_id}),
+        )
 
-            while True:
-                result = connection.execute(
-                    sa.text(
-                        """
-                        UPDATE flow_run 
-                        SET work_queue_id=:id 
-                        WHERE flow_run.id in (
-                            SELECT id 
-                            FROM flow_run 
-                            WHERE flow_run.work_queue_id IS NULL and flow_run.work_queue_name=:name 
-                            LIMIT :batch_size
-                        )
-                        """
-                    ).params({"id": row[0], "name": row[1], "batch_size": batch_size}),
-                )
-                if result.rowcount <= batch_size:
-                    break
+        default_queue_id = connection.execute(
+            sa.text(
+                "SELECT id FROM work_queue WHERE name = 'default' and work_pool_id ="
+                " :default_pool_id"
+            ).params({"default_pool_id": default_pool_id}),
+        ).fetchone()[0]
 
-            while True:
-                result = connection.execute(
+        connection.execute(
+            sa.text(
+                "UPDATE work_pool SET default_queue_id = :default_queue_id WHERE id ="
+                " :default_pool_id"
+            ).params(
+                {
+                    "default_pool_id": default_pool_id,
+                    "default_queue_id": default_queue_id,
+                }
+            ),
+        )
+
+        # Set priority on all queues and update flow runs and deployments
+        queue_rows = connection.execute(
+            sa.text(
+                "SELECT id, name FROM work_queue WHERE work_pool_id = :default_pool_id"
+            ).params({"default_pool_id": default_pool_id}),
+        ).fetchall()
+
+        with op.get_context().autocommit_block():
+            for enumeration, row in enumerate(queue_rows):
+                connection.execute(
                     sa.text(
-                        """
-                        UPDATE deployment 
-                        SET work_queue_id=:id 
-                        WHERE deployment.id in (
-                            SELECT id 
-                            FROM deployment 
-                            WHERE deployment.work_queue_id IS NULL and deployment.work_queue_name=:name 
-                            LIMIT :batch_size
-                        )
-                        """
-                    ).params({"id": row[0], "name": row[1], "batch_size": batch_size}),
+                        "UPDATE work_queue SET priority = :priority WHERE id = :id"
+                    ).params({"priority": enumeration + 1, "id": row[0]}),
                 )
-                if result.rowcount <= batch_size:
-                    break
+
+                batch_size = 250
+
+                while True:
+                    result = connection.execute(
+                        sa.text(
+                            """
+                            UPDATE flow_run 
+                            SET work_queue_id=:id 
+                            WHERE flow_run.id in (
+                                SELECT id 
+                                FROM flow_run 
+                                WHERE flow_run.work_queue_id IS NULL and flow_run.work_queue_name=:name 
+                                LIMIT :batch_size
+                            )
+                            """
+                        ).params(
+                            {"id": row[0], "name": row[1], "batch_size": batch_size}
+                        ),
+                    )
+                    if result.rowcount <= batch_size:
+                        break
+
+                while True:
+                    result = connection.execute(
+                        sa.text(
+                            """
+                            UPDATE deployment 
+                            SET work_queue_id=:id 
+                            WHERE deployment.id in (
+                                SELECT id 
+                                FROM deployment 
+                                WHERE deployment.work_queue_id IS NULL and deployment.work_queue_name=:name 
+                                LIMIT :batch_size
+                            )
+                            """
+                        ).params(
+                            {"id": row[0], "name": row[1], "batch_size": batch_size}
+                        ),
+                    )
+                    if result.rowcount <= batch_size:
+                        break
 
     with op.batch_alter_table("work_queue", schema=None) as batch_op:
         batch_op.drop_constraint("uq_work_queue__name")
diff --git a/src/prefect/server/database/migrations/versions/sqlite/2023_01_31_105442_1678f2fb8b33_work_queue_data_migration.py b/src/prefect/server/database/migrations/versions/sqlite/2023_01_31_105442_1678f2fb8b33_work_queue_data_migration.py
--- a/src/prefect/server/database/migrations/versions/sqlite/2023_01_31_105442_1678f2fb8b33_work_queue_data_migration.py
+++ b/src/prefect/server/database/migrations/versions/sqlite/2023_01_31_105442_1678f2fb8b33_work_queue_data_migration.py
@@ -29,104 +29,116 @@ def upgrade():
     # Create default agent work pool and associate all existing queues with it
     connection = op.get_bind()
 
-    connection.execute(
-        sa.text(
-            "INSERT INTO work_pool (name, type) VALUES ('default-agent-pool',"
-            " 'prefect-agent')"
-        )
-    )
-
-    default_pool_id = connection.execute(
-        sa.text("SELECT id FROM work_pool WHERE name = 'default-agent-pool'")
+    n_work_queues_without_a_work_pool = connection.execute(
+        sa.text("SELECT COUNT(*) FROM work_queue WHERE work_pool_id IS NULL")
     ).fetchone()[0]
 
-    default_queue = connection.execute(
-        sa.text("SELECT id FROM work_queue WHERE name = 'default'")
-    ).fetchone()
-
-    if not default_queue:
+    if n_work_queues_without_a_work_pool > 0:
         connection.execute(
             sa.text(
-                "INSERT INTO work_queue (name, work_pool_id) VALUES ('default',"
-                " :default_pool_id)"
-            ).params({"default_pool_id": default_pool_id}),
+                "INSERT INTO work_pool (name, type) VALUES ('default-agent-pool',"
+                " 'prefect-agent')"
+            )
         )
 
-    connection.execute(
-        sa.text(
-            "UPDATE work_queue SET work_pool_id = :default_pool_id WHERE work_pool_id"
-            " IS NULL"
-        ).params({"default_pool_id": default_pool_id}),
-    )
-
-    default_queue_id = connection.execute(
-        sa.text(
-            "SELECT id FROM work_queue WHERE name = 'default' and work_pool_id ="
-            " :default_pool_id"
-        ).params({"default_pool_id": default_pool_id}),
-    ).fetchone()[0]
+        default_pool_id = connection.execute(
+            sa.text("SELECT id FROM work_pool WHERE name = 'default-agent-pool'")
+        ).fetchone()[0]
 
-    connection.execute(
-        sa.text(
-            "UPDATE work_pool SET default_queue_id = :default_queue_id WHERE id ="
-            " :default_pool_id"
-        ).params(
-            {"default_pool_id": default_pool_id, "default_queue_id": default_queue_id}
-        ),
-    )
-
-    # Set priority on all queues and update flow runs and deployments
-    queue_rows = connection.execute(
-        sa.text(
-            "SELECT id, name FROM work_queue WHERE work_pool_id = :default_pool_id"
-        ).params({"default_pool_id": default_pool_id}),
-    ).fetchall()
+        default_queue = connection.execute(
+            sa.text("SELECT id FROM work_queue WHERE name = 'default'")
+        ).fetchone()
 
-    with op.get_context().autocommit_block():
-        for enumeration, row in enumerate(queue_rows):
+        if not default_queue:
             connection.execute(
                 sa.text(
-                    "UPDATE work_queue SET priority = :priority WHERE id = :id"
-                ).params({"priority": enumeration + 1, "id": row[0]}),
+                    "INSERT INTO work_queue (name, work_pool_id) VALUES ('default',"
+                    " :default_pool_id)"
+                ).params({"default_pool_id": default_pool_id}),
             )
 
-            batch_size = 250
+        connection.execute(
+            sa.text(
+                "UPDATE work_queue SET work_pool_id = :default_pool_id WHERE work_pool_id"
+                " IS NULL"
+            ).params({"default_pool_id": default_pool_id}),
+        )
 
-            while True:
-                result = connection.execute(
-                    sa.text(
-                        """
-                        UPDATE flow_run 
-                        SET work_queue_id=:id 
-                        WHERE flow_run.id in (
-                            SELECT id 
-                            FROM flow_run 
-                            WHERE flow_run.work_queue_id IS NULL and flow_run.work_queue_name=:name 
-                            LIMIT :batch_size
-                        )
-                        """
-                    ).params({"id": row[0], "name": row[1], "batch_size": batch_size}),
-                )
-                if result.rowcount <= batch_size:
-                    break
+        default_queue_id = connection.execute(
+            sa.text(
+                "SELECT id FROM work_queue WHERE name = 'default' and work_pool_id ="
+                " :default_pool_id"
+            ).params({"default_pool_id": default_pool_id}),
+        ).fetchone()[0]
 
-            while True:
-                result = connection.execute(
+        connection.execute(
+            sa.text(
+                "UPDATE work_pool SET default_queue_id = :default_queue_id WHERE id ="
+                " :default_pool_id"
+            ).params(
+                {
+                    "default_pool_id": default_pool_id,
+                    "default_queue_id": default_queue_id,
+                }
+            ),
+        )
+
+        # Set priority on all queues and update flow runs and deployments
+        queue_rows = connection.execute(
+            sa.text(
+                "SELECT id, name FROM work_queue WHERE work_pool_id = :default_pool_id"
+            ).params({"default_pool_id": default_pool_id}),
+        ).fetchall()
+
+        with op.get_context().autocommit_block():
+            for enumeration, row in enumerate(queue_rows):
+                connection.execute(
                     sa.text(
-                        """
-                        UPDATE deployment 
-                        SET work_queue_id=:id 
-                        WHERE deployment.id in (
-                            SELECT id 
-                            FROM deployment 
-                            WHERE deployment.work_queue_id IS NULL and deployment.work_queue_name=:name 
-                            LIMIT :batch_size
-                        )
-                        """
-                    ).params({"id": row[0], "name": row[1], "batch_size": batch_size}),
+                        "UPDATE work_queue SET priority = :priority WHERE id = :id"
+                    ).params({"priority": enumeration + 1, "id": row[0]}),
                 )
-                if result.rowcount <= batch_size:
-                    break
+
+                batch_size = 250
+
+                while True:
+                    result = connection.execute(
+                        sa.text(
+                            """
+                            UPDATE flow_run 
+                            SET work_queue_id=:id 
+                            WHERE flow_run.id in (
+                                SELECT id 
+                                FROM flow_run 
+                                WHERE flow_run.work_queue_id IS NULL and flow_run.work_queue_name=:name 
+                                LIMIT :batch_size
+                            )
+                            """
+                        ).params(
+                            {"id": row[0], "name": row[1], "batch_size": batch_size}
+                        ),
+                    )
+                    if result.rowcount <= batch_size:
+                        break
+
+                while True:
+                    result = connection.execute(
+                        sa.text(
+                            """
+                            UPDATE deployment 
+                            SET work_queue_id=:id 
+                            WHERE deployment.id in (
+                                SELECT id 
+                                FROM deployment 
+                                WHERE deployment.work_queue_id IS NULL and deployment.work_queue_name=:name 
+                                LIMIT :batch_size
+                            )
+                            """
+                        ).params(
+                            {"id": row[0], "name": row[1], "batch_size": batch_size}
+                        ),
+                    )
+                    if result.rowcount <= batch_size:
+                        break
 
     with op.batch_alter_table("work_queue", schema=None) as batch_op:
         batch_op.drop_constraint("uq_work_queue__name")


Test patch:
diff --git a/tests/server/database/test_migrations.py b/tests/server/database/test_migrations.py
--- a/tests/server/database/test_migrations.py
+++ b/tests/server/database/test_migrations.py
@@ -590,3 +590,90 @@ async def test_adding_default_agent_pool_without_existing_default_queue_migratio
 
     finally:
         await run_sync_in_worker_thread(alembic_upgrade)
+
+
+async def test_not_adding_default_agent_pool_when_all_work_queues_have_work_pool(db):
+    connection_url = PREFECT_API_DATABASE_CONNECTION_URL.value()
+    dialect = get_dialect(connection_url)
+
+    # get the proper migration revisions
+    if dialect.name == "postgresql":
+        revisions = ("0a1250a5aa25", "f98ae6d8e2cc")
+    else:
+        revisions = ("b9bda9f142f1", "1678f2fb8b33")
+
+    try:
+        await run_sync_in_worker_thread(alembic_downgrade, revision=revisions[0])
+
+        session = await db.session()
+        async with session:
+            # clear the work queue table
+            await session.execute(sa.text("DELETE FROM work_queue;"))
+            await session.commit()
+
+            # insert some work queues with a work pool into the database
+            await session.execute(
+                sa.text(
+                    "INSERT INTO work_pool (name, type) VALUES ('existing-pool', 'prefect-agent');"
+                )
+            )
+            existing_pool_id = (
+                await session.execute(
+                    sa.text("SELECT id FROM work_pool WHERE name = 'existing-pool';")
+                )
+            ).scalar()
+
+            await session.execute(
+                sa.text(
+                    "INSERT INTO work_queue (name, work_pool_id) VALUES ('queue-1', :existing_pool_id);"
+                ),
+                {"existing_pool_id": existing_pool_id},
+            )
+            await session.execute(
+                sa.text(
+                    "INSERT INTO work_queue (name, work_pool_id) VALUES ('queue-2', :existing_pool_id);"
+                ),
+                {"existing_pool_id": existing_pool_id},
+            )
+            await session.execute(
+                sa.text(
+                    "INSERT INTO work_queue (name, work_pool_id) VALUES ('queue-3', :existing_pool_id);"
+                ),
+                {"existing_pool_id": existing_pool_id},
+            )
+            await session.commit()
+
+        async with session:
+            # Confirm the work queues are present
+            pre_work_queue_names = (
+                await session.execute(sa.text("SELECT name FROM work_queue;"))
+            ).fetchall()
+
+            assert len(pre_work_queue_names) == 3
+
+        # run the migration
+        await run_sync_in_worker_thread(alembic_upgrade, revision=revisions[1])
+
+        session = await db.session()
+        async with session:
+            # Check that the default-agent-pool is not created
+            default_pool_exists = (
+                await session.execute(
+                    sa.text(
+                        "SELECT COUNT(*) FROM work_pool WHERE name = 'default-agent-pool';"
+                    )
+                )
+            ).scalar()
+
+            assert default_pool_exists == 0
+
+            # Check that the existing work queues are not modified
+            work_queue_names = (
+                await session.execute(sa.text("SELECT name FROM work_queue;"))
+            ).fetchall()
+
+            assert len(work_queue_names) == 3
+            assert set(work_queue_names) == set(pre_work_queue_names)
+
+    finally:
+        await run_sync_in_worker_thread(alembic_upgrade)