diff --git a/changelog/54938.fixed.md b/changelog/54938.fixed.md new file mode 100644 index 00000000000..4977bc950fb --- /dev/null +++ b/changelog/54938.fixed.md @@ -0,0 +1 @@ +Fixed mysql.db_remove so it correctly refuses to drop the information_schema system database, which was previously misspelled as information_scheme. diff --git a/salt/modules/mysql.py b/salt/modules/mysql.py index 55ba7fde073..141b48bf73d 100644 --- a/salt/modules/mysql.py +++ b/salt/modules/mysql.py @@ -1364,7 +1364,7 @@ def db_remove(name, **connection_args): log.info("DB '%s' does not exist", name) return False - if name in ("mysql", "information_scheme"): + if name in ("mysql", "information_schema"): log.info("DB '%s' may not be removed", name) return False diff --git a/tests/pytests/unit/modules/test_mysql.py b/tests/pytests/unit/modules/test_mysql.py index 2023f649877..93af2d04255 100644 --- a/tests/pytests/unit/modules/test_mysql.py +++ b/tests/pytests/unit/modules/test_mysql.py @@ -483,6 +483,48 @@ def test_db_remove(): _test_call(mysql.db_remove, "DROP DATABASE `test``'\" db`;", "test`'\" db") +def test_db_remove_system_db(): + """ + Test that MySQL db_remove refuses to drop the protected system databases + and never issues a DROP for them (regression test for #54938 where + "information_schema" was misspelled as "information_scheme"). + """ + for name in ("mysql", "information_schema"): + connect_mock = MagicMock() + with patch.object( + mysql, "db_exists", MagicMock(return_value=True) + ), patch.object(mysql, "_connect", connect_mock): + assert mysql.db_remove(name) is False + connect_mock.assert_not_called() + + +def test_db_remove_allows_db_named_information_scheme_54938(): + """ + Test that db_remove issues DROP DATABASE for a user database literally + named "information_scheme" (the misspelling that used to sit in the + system-database guard before #54938 was fixed). Called the same way the + production caller mysql_database.absent() calls it: just the database + name, with connection_args empty. + """ + with patch.object(mysql, "db_exists", MagicMock(return_value=True)): + _test_call( + mysql.db_remove, "DROP DATABASE `information_scheme`;", "information_scheme" + ) + + +def test_db_remove_does_not_block_similar_names_54938(): + """ + Guard against overcorrection of the #54938 fix: db_remove must still + issue DROP DATABASE for user databases whose names merely resemble the + protected system databases. This test passes with and without the fix + applied. Like the production caller mysql_database.absent(), db_remove + is called with just the database name (connection_args empty). + """ + for name in ("mysql_backup", "information_schema_old"): + with patch.object(mysql, "db_exists", MagicMock(return_value=True)): + _test_call(mysql.db_remove, f"DROP DATABASE `{name}`;", name) + + def test_db_tables(): """ Test MySQL db_tables function in mysql exec module