Story #4716
Updated by dalley over 5 years ago
Simple content copy means that a list of content units can be copied from one repository into another repository without considering content-type-specific invariants, such as making sure dependencies are satisfied.
The most straightforwards current design is to model this after one-shot upload. A new URL endpoint will be defined at /api/v3/rpm/copy/. POSTing to that endpoint with valid parameters will yield an asynchronous task, which will result in a new repository version in the target repository.
The user workflow should look like this:
<pre>
http --form POST http://localhost:24817/pulp/api/v3/rpm/copy/ source_repository=${S_REPO_HREF} destination_repository=${D_REPO_HREF} content_set:="[\"$CONTENT_1_HREF\", \"$CONTENT_2_HREF\"]"
</pre>
Both the repository parameters are required. The content_set parameter is not required; if excluded, all content will be copied.
The additions to Django boilerplate will look something like this (see also: copy.py for an example of the function that does the work)
urls.py
<pre><code class="python">
urlpatterns = [
url(r'rpm/upload/$', OneShotUploadView.as_view()),
url(r'rpm/copy/$', CopyView.as_view())
]
</code></pre>
viewsets.py
<pre><code class="python">
class CopyView(views.APIView):
def post(self, request):
serializer = CopySerializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
# .....
async_result = enqueue_with_reservation(
copy_content, [...], # function to perform the copying, and arguments to provide it
kwargs={
'source_repo': ...,
'dest_repo': ....,
'content_set': ...,
# ....
}
)
return OperationPostponedResponse(async_result, request)
</code></pre>
serializers.py
<pre><code class="python">
class CopySerializer(serializers.Serializer):
source_repository = serializers.HyperlinkedRelatedField(
help_text=_('A URI of the repository.'),
required=True,
queryset=Repository.objects.all(),
view_name='repositories-detail',
)
destination_repository = serializers.HyperlinkedRelatedField(
help_text=_('A URI of the repository.'),
required=True,
queryset=Repository.objects.all(),
view_name='repositories-detail',
)
content_set = serializers.ListField(
help_text=_('A list of content units to copy to a new repository version'),
write_only=True,
required=True,
)
</code></pre>
Outstanding questions:
# The exact names of the parameters, e.g. destination_repository vs target_repository, *repository vs. *repo, "content_set"
# Whether those is sufficient for the most basic implementation
# Whether doing a full copy when content_set is unspecified is appropriate