diff --git a/CHANGES/5501.bugfix b/CHANGES/5501.bugfix new file mode 100644 index 0000000000..33cdf5ef6f --- /dev/null +++ b/CHANGES/5501.bugfix @@ -0,0 +1 @@ +Fixed content upload for existing on-demand content not properly storing the new artifact. diff --git a/pulpcore/app/serializers/content.py b/pulpcore/app/serializers/content.py index fcb62c80a8..907ca514cc 100644 --- a/pulpcore/app/serializers/content.py +++ b/pulpcore/app/serializers/content.py @@ -60,6 +60,7 @@ def create(self, validated_data): artifacts = self.get_artifacts(validated_data) content = self.retrieve(validated_data) + created = False if content is not None: content.touch() else: @@ -74,6 +75,22 @@ def create(self, validated_data): content = self.retrieve(validated_data) if content is None: raise + else: + created = True + # Ensure the content now has the uploaded artifact(s) + if not created: + ca_set = content.contentartifact_set + if ca_set.count() == 0 or ca_set.filter(artifact=None).exists(): + cas = [ + models.ContentArtifact(artifact=a, content=content, relative_path=rp) + for rp, a in artifacts.items() + ] + models.ContentArtifact.objects.bulk_create( + cas, + update_conflicts=True, + update_fields=["artifact"], + unique_fields=["content", "relative_path"], + ) if repository: repository.cast() diff --git a/pulpcore/tests/functional/api/using_plugin/test_content_access.py b/pulpcore/tests/functional/api/using_plugin/test_content_access.py index d6c88fbe26..9029374865 100644 --- a/pulpcore/tests/functional/api/using_plugin/test_content_access.py +++ b/pulpcore/tests/functional/api/using_plugin/test_content_access.py @@ -40,3 +40,32 @@ def test_file_remote_on_demand( distribution = file_distribution_factory(repository=repo.pulp_href) # attempt to download_file() a file download_file(f"{distribution.base_url}/1.iso") + + +@pytest.mark.parallel +def test_upload_file_on_demand_already( + basic_manifest_path, + file_fixtures_root, + file_remote_factory, + file_repo, + file_bindings, + monitor_task, +): + """Test that on-demand content can be uploaded to Pulp and become immediate content.""" + remote = file_remote_factory(basic_manifest_path, policy="on_demand") + body = {"remote": remote.pulp_href} + monitor_task(file_bindings.RepositoriesFileApi.sync(file_repo.pulp_href, body).task) + file_repo = file_bindings.RepositoriesFileApi.read(file_repo.pulp_href) + result = file_bindings.ContentFilesApi.list(repository_version=file_repo.latest_version_href) + assert result.count == 3 + for content in result.results: + assert content.artifact is None + + file_content = file_fixtures_root / "basic" / content.relative_path + body = {"relative_path": content.relative_path, "file": file_content} + task = monitor_task(file_bindings.ContentFilesApi.create(**body).task) + assert len(task.created_resources) == 1 + assert task.created_resources[0] == content.pulp_href + + content = file_bindings.ContentFilesApi.read(content.pulp_href) + assert content.artifact is not None