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) (but see also, OneShotUploadSerializer in serializers.py and copy.py). 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