diff --git a/CHANGES/7677.bugfix b/CHANGES/7677.bugfix new file mode 100644 index 00000000000..ecedf6c8d6d --- /dev/null +++ b/CHANGES/7677.bugfix @@ -0,0 +1 @@ +Allow nested downloader_config to be passed json stringified. diff --git a/pulp_file/tests/functional/api/test_crud_content_unit.py b/pulp_file/tests/functional/api/test_crud_content_unit.py index bf7fbe19bde..04aedc53d4b 100644 --- a/pulp_file/tests/functional/api/test_crud_content_unit.py +++ b/pulp_file/tests/functional/api/test_crud_content_unit.py @@ -296,7 +296,11 @@ def test_create_file_from_url( ): # Test create w/ url remote = file_remote_factory(manifest_path=basic_manifest_path) - body = {"file_url": remote.url, "relative_path": "PULP_MANIFEST"} + body = { + "file_url": remote.url, + "relative_path": "PULP_MANIFEST", + "downloader_config": {"total_timeout": 5}, + } response = file_bindings.ContentFilesApi.create(**body) task = monitor_task(response.task) assert len(task.created_resources) == 1 diff --git a/pulpcore/app/serializers/base.py b/pulpcore/app/serializers/base.py index 17d26c3b5fd..b130449f262 100644 --- a/pulpcore/app/serializers/base.py +++ b/pulpcore/app/serializers/base.py @@ -1,4 +1,5 @@ import functools +import json import re import traceback from collections import namedtuple @@ -80,7 +81,7 @@ def to_internal_value(self, data): return super().to_internal_value(data) -class _MatchingRegexViewName(object): +class _MatchingRegexViewName: """This is a helper class to help defining object matching rules for master-detail. If you can be specific, please specify the `view_name`, but if you cannot, this allows @@ -778,6 +779,17 @@ def _validate_certificate(which_cert, value): "Invalid {} specified, error '{}'".format(which_cert, e.args) ) + def to_internal_value(self, data): + if isinstance(data, str): + try: + # Nested Serializers in from-urlencoded bodies are stringified as json by default. + data = json.loads(data) + except json.DecodeError: + raise serializers.ValidationError( + "Invalid json data for (nested) downloader config." + ) + return super().to_internal_value(data) + def validate(self, data): """ Check that proxy credentials are only provided completely and if a proxy is configured.