From d69dffb2ca3bbbf01d418614796882de954b92d8 Mon Sep 17 00:00:00 2001 From: Jitka Halova Date: Mon, 30 Mar 2026 18:01:20 +0200 Subject: [PATCH] Add created_resource_prns field to Task closes #7003 Assisted By: Claude Opus 4.6 --- CHANGES/7003.feature | 1 + pulpcore/app/serializers/task.py | 29 ++++++++++++++++++- .../functional/api/using_plugin/test_tasks.py | 23 +++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 CHANGES/7003.feature diff --git a/CHANGES/7003.feature b/CHANGES/7003.feature new file mode 100644 index 00000000000..71825a46d1b --- /dev/null +++ b/CHANGES/7003.feature @@ -0,0 +1 @@ +Added the `created_resource_prns` field to Task, returning the PRN of each created resource. diff --git a/pulpcore/app/serializers/task.py b/pulpcore/app/serializers/task.py index 998a8727447..ef5c16f52e1 100644 --- a/pulpcore/app/serializers/task.py +++ b/pulpcore/app/serializers/task.py @@ -17,7 +17,7 @@ fields, ) from pulpcore.constants import TASK_STATES -from pulpcore.app.util import reverse +from pulpcore.app.util import get_prn, reverse class CreatedResourceField(RelatedResourceField): @@ -26,6 +26,25 @@ class Meta: fields = [] +class CreatedResourcePrnField(RelatedResourceField): + """ + A field that returns PRNs for created resources instead of HREFs. + """ + + def to_representation(self, data): + # If content_type is already cached, build PRN without a DB hit + if models.GenericRelationModel.content_type.is_cached(data): + model = data.content_type.model_class() + return f"prn:{model._meta.label_lower}:{data.object_id}" + if data.content_object is None: + return "" + return get_prn(instance=data.content_object) + + class Meta: + model = models.CreatedResource + fields = [] + + class TaskSerializer(ModelSerializer): pulp_href = IdentityField(view_name="tasks-detail") state = serializers.CharField( @@ -82,6 +101,13 @@ class TaskSerializer(ModelSerializer): read_only=True, view_name="None", # This is a polymorphic field. The serializer does not need a view name. ) + created_resource_prns = CreatedResourcePrnField( + help_text=_("Resources created by this task as PRNs."), + many=True, + read_only=True, + view_name="None", # This is a polymorphic field. The serializer does not need a view name. + source="created_resources", + ) reserved_resources_record = serializers.ListField( child=serializers.CharField(), help_text=_("A list of resources required by that task."), @@ -120,6 +146,7 @@ class Meta: "task_group", "progress_reports", "created_resources", + "created_resource_prns", "reserved_resources_record", "result", ) diff --git a/pulpcore/tests/functional/api/using_plugin/test_tasks.py b/pulpcore/tests/functional/api/using_plugin/test_tasks.py index 3280e3d689e..8013a0bf587 100644 --- a/pulpcore/tests/functional/api/using_plugin/test_tasks.py +++ b/pulpcore/tests/functional/api/using_plugin/test_tasks.py @@ -189,3 +189,26 @@ def test_task_result(add_to_cleanup, file_bindings, monitor_task): assert task_2.result["base_path"] == updated_body["base_path"] add_to_cleanup(file_bindings.DistributionsFileApi, dist_href) + + +@pytest.mark.parallel +def test_created_resource_prns( + basic_manifest_path, + file_bindings, + file_remote_factory, + file_repo, + monitor_task, +): + """ + Test that created_resource_prns returns PRNs matching the created resources. + """ + remote = file_remote_factory(basic_manifest_path) + task = monitor_task( + file_bindings.RepositoriesFileApi.sync(file_repo.pulp_href, {"remote": remote.prn}).task + ) + assert len(task.created_resources) == 1 + assert len(task.created_resource_prns) == 1 + + # The PRN should correspond to the repository version that was created + repo_ver = file_bindings.RepositoriesFileVersionsApi.read(task.created_resources[0]) + assert repo_ver.prn == task.created_resource_prns[0] == task.result["prn"]