diff --git a/cloudinit/cmd/main.py b/cloudinit/cmd/main.py index d1ff6ba7660..883b1da4c1e 100644 --- a/cloudinit/cmd/main.py +++ b/cloudinit/cmd/main.py @@ -344,7 +344,7 @@ def _should_wait_via_user_data( version="24.4", requested_level=logging.WARNING, msg="Unexpected failure parsing userdata: %s", - args=e, + args=(e,), ) return True, "failed to parse user data as yaml" diff --git a/cloudinit/config/schema.py b/cloudinit/config/schema.py index f305fc12e29..08e956b66d6 100644 --- a/cloudinit/config/schema.py +++ b/cloudinit/config/schema.py @@ -1457,6 +1457,26 @@ def handle_schema_args(name, args): ) +def get_meta_doc(*_args, **_kwargs) -> str: + """Provide a stub for backwards compatibility. + + This function is no longer used, but earlier versions of modules + required this function for documentation purposes. This is a stub so + that custom modules do not break on upgrade. + """ + lifecycle.log_with_downgradable_level( + logger=LOG, + version="24.4", + requested_level=logging.WARNING, + msg=( + "The 'get_meta_doc()' function is deprecated and will be removed " + "in a future version of cloud-init." + ), + args=(), + ) + return "" + + def main(): """Tool to validate schema of a cloud-config file or print schema docs.""" parser = get_parser() diff --git a/cloudinit/lifecycle.py b/cloudinit/lifecycle.py index 2102d03da32..5484fb3a626 100644 --- a/cloudinit/lifecycle.py +++ b/cloudinit/lifecycle.py @@ -128,7 +128,7 @@ def log_with_downgradable_level( version: str, requested_level: int, msg: str, - args, + args: tuple, ): """Log a message at the requested level, if that is acceptable. @@ -145,9 +145,9 @@ def log_with_downgradable_level( :return: True if the message should be logged, else False. """ if should_log_deprecation(version, features.DEPRECATION_INFO_BOUNDARY): - logger.log(requested_level, msg, args) + logger.log(requested_level, msg, *args) else: - logger.debug(msg, args) + logger.debug(msg, *args) def deprecate( diff --git a/tests/unittests/cloudinit/test_lifecycle.py b/tests/unittests/cloudinit/test_lifecycle.py new file mode 100644 index 00000000000..f17f647eec9 --- /dev/null +++ b/tests/unittests/cloudinit/test_lifecycle.py @@ -0,0 +1,32 @@ +import logging + +import pytest + +from cloudinit import lifecycle + +LOG = logging.getLogger() + + +class TestLogWithDowngradableLevel: + @pytest.mark.parametrize( + "version,expected", + [ + ("9", logging.ERROR), + ("11", logging.DEBUG), + ], + ) + def test_log_with_downgradable_level( + self, mocker, caplog, version, expected + ): + mocker.patch("cloudinit.features.DEPRECATION_INFO_BOUNDARY", "10") + lifecycle.log_with_downgradable_level( + logger=LOG, + version=version, + requested_level=logging.ERROR, + msg="look at me %s %s!", + args=("one", "two"), + ) + records = caplog.record_tuples + assert len(records) == 1 + assert records[0][1] == expected + assert records[0][2] == "look at me one two!" diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py index a7d66f021af..19195b2bbe0 100644 --- a/tests/unittests/config/test_schema.py +++ b/tests/unittests/config/test_schema.py @@ -27,6 +27,7 @@ SchemaValidationError, annotated_cloudconfig_file, get_jsonschema_validator, + get_meta_doc, get_schema, get_schema_dir, handle_schema_args, @@ -2278,3 +2279,14 @@ def test_handle_schema_args_unknown_header( assert read_cfg_paths.call_args_list == [ mock.call(fetch_existing_datasource="trust") ] + + +class TestDeprecation: + def test_get_meta_doc_deprecation(self, caplog): + """Test that calling get_meta_doc() emits deprecation. + + Ensures that custom modules calling `get_meta_doc()` can still + function but receive deprecation warning. + """ + get_meta_doc("some", "random", "arguments", plus="kwargs") + assert "The 'get_meta_doc()' function is deprecated" in caplog.text