<div dir="ltr"><div><div><div><div>Here is another idea that would remove the verbs from the REST API and would provide a way to namespace plugin provided tasks. <br></div><div><br>We could add 2 additional resource types for plugin writers to 
provide: versionaction and publicationaction. These REST resources would only
 support GET requests. The response would contain a description of the 
action and  a description of the parameters this action accepts. Plugin writers would create these resources by extending an ActionView with a custom get() method for providing users with a description and also an action() method which would contain the code that needs to run asynchronously. <br><br>Every
 repository version would be created using the repository version API. 
POST requests to the repository version API would accept a 
'versionaction' href along with a dictionary of parameters. Users would 
then receive a 202 response with a task href that can be used to monitor
 the progress of the asynchronous repository version creation. <br><br>Every
 publication would be created using the publication API. POST requests 
to the publication API would accept a 'publicationaction' href along 
with a dictionary of parameters. Users would then receive a 202 response
 with a task href that can be 
used to monitor the progress of the asynchronous publication
creation. <br><br></div><div>Here are some REST API changes this would bring:<br></div><div><b><br>/api/v3/versionactions/</b> - returns a list of all the action descriptions for creating repository versions<br><br></div><div><b>/api/v3/versionactions/</b><wbr><b>pulpcore/addremove/</b> - returns a description of the addremove action provided by pulpcore. Something like this:<br><br>{<br>   'href': '<a href="http://localhost/api/v3/versionactions/pulpcore/addremove/">http://localhost/api/v3/versionactions/pulpcore/addremove/</a>', <br>   'description': 'Creates a repository version by adding and removing content units from the latest repository version.',<br>   'parameters': {<br>                              'add_content_units': 'list of content to add',<br></div><div>                              'remove_content_units': 'list of content to remove'<br>                           }<br>}<br><br><br></div><b>/api/v3/versionactions/<</b><wbr><b>plugin>/sync/ </b>- accepts GET and returns a description of the sync action of the plugin. Something like this:<br><br><div>{<br>   'href': '<a href="http://localhost/api/v3/versionactions/file/sync/">http://localhost/api/v3/versionactions/file/sync/</a>', <br>   'description': 'Creates a repository version by syncing content from a remote file repository.',<br>   'parameters': {<br>                              'remote': 'href of the remote to sync from'<br>                           }<br>}</div><br><b><br></b></div><b>/api/v3/publicationactions/ </b>- returns a list of all the actions for creating publications<br><br></div><b>/api/v3/publicationactions/<</b><wbr><b>plugin>/publish/</b> - accepts GET and returns a description of the publish action for the file plugin. Something like this:<br><br>{<br>   'href': '<a href="http://localhost/api/v3/versionactions/file/publish/">http://localhost/api/v3/versionactions/file/publish/</a>', <br>   'description': 'Create a publication from a file repository version.',<br>   'parameters': {<br>                             
 'repository': 'href of the repository to publish. The latest repository
 version will be published. Can only be specified if repository_version 
is not specified.'<br>                              'repository_version': 'href of the repository version to 
publish. Can only be specified if repository_version is not specified. Can only be specified if repository is not specified.'<br>                           }<br>}<br><br></div><div><b>/api/v3/repository/<uuid>/versions/ </b>- accepts POST requests with 'versionaction' href and 'parameters' dictionary. Returns 202 with a task href. <br><br></div><div><b>/api/v3/publications/ </b>- accepts POST requests with 'publicationaction' href and 'parameters' dictionary. Returns 202 with a task href. <br></div><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 29, 2018 at 4:18 PM, Milan Kovacik <span dir="ltr"><<a href="mailto:mkovacik@redhat.com" target="_blank">mkovacik@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Folks,<br>
<br>
I'd like to summarize where we've gotten so far. Our problem statement<br>
is threefold:<br>
<br>
1) Content operations have to be routed thru particular plug-ins i.e<br>
no repository version can be created without a plug-in involvement, to<br>
avoid repository content consistency/correctness issues<br>
2) API specialization i.e keeping core concepts above plug-in specific<br>
concepts; e.g CRUD@/v3/repositories/ v.s CRUD@docker/adds/<br>
3) API consistency i.e preferably where I create it is where I manage<br>
it; e.g. w/r/t asynchronous action endpoints creating Task resources<br>
vs a Task management endpoint<br>
<br>
Since there is a significant intersection between the asynchronous<br>
action endpoints and endpoints manipulating repository versions<br>
asynchronously, me and Austin propose to convert the asynchronous<br>
action endpoints to Task management endpoints, in full control of<br>
plug-ins, in particular:<br>
<br>
Asynchronous Repository Version Management Endpoints:<br>
<br>
  Repository synchronisation and publication and addition(deletion) of<br>
content into(from) a repository version would all be treated as Task<br>
objects primarily, residing in the plug-in namespace:<br>
      POST@/v3/tasks/<plug-in>/[<wbr>syncs, publishes, additions, deletions]/<br>
  because all these operations share similar call signature, every one<br>
of these actions:<br>
<br>
  * creates a Task object<br>
  * the task, while executing, creates a new repository version and<br>
locks similar resources<br>
  * has to be controlled by a particular plug-in i.e may require<br>
additional, plug-in specific settings<br>
  * requires either a repository URI or repository version URI to operate on<br>
  * requires generic action configuration e.g almost every sync<br>
requires (at least one) importer<br>
<br>
 As a result:<br>
   * the asynchronous content management Task is now the nexus where<br>
the configuration (repository, plug-in, origin) meets the action<br>
   * these complex tasks that actually do the heavy lifting have a<br>
clear management endpoint<br>
   * this change effectively renders the<br>
@/v3/repositories/<UUID>/<wbr>versions/<#nr>/ endpoint read-only and<br>
documents the intention that no repository version is ever created<br>
without an actual plug-in involvement<br>
   * a plug-in can expose custom asynchronous content endpoints, that<br>
manipulate repository versions, aligned with the more generic actions:<br>
           POST@/v3/tasks/<plug-in>/[<<wbr>custom asynchronous repository<br>
version management action>,...]/<br>
   * the design aligns better with the DRF allowing (nested)<br>
serializers to control (and document) the endpoints in the direction<br>
from the more generic to the more specific implementation<br>
<br>
Asynchronous Core Object Management Endpoints:<br>
<br>
  Additionally, for Asynchronous Core object management endpoints, we<br>
suggest to move Remote/Importer, Publisher, Exporter, Repository<br>
operations under a new core task namespace:<br>
       POST@/v3/tasks/core/[<wbr>importers, publishers,<br>
repositories]/[deletes, updates]/<br>
  to be consistent with the asynchronous content actions. This however<br>
seems to conflict with 3).<br>
<br>
Caveats<br>
<br>
Both the current and the proposed design don't conceptually prevent a<br>
repository to have content provided by multiple plug-ins.<br>
Folks don't like Pulp becoming a task management system.<br>
<br>
Alternatives<br>
<br>
  Dennis proposes to achieve similar result by adding plug-in content<br>
model hooks:<br>
      "add_to_repository_version" and "remove_from_repository_<wbr>version"<br>
  This approach however doesn't seem to solve plug-ins requiring<br>
multiple or no importers and leaves multiple spots in the API, where<br>
repository versions can be created (failing 3); custom plug-in<br>
asynchronous content management endpoints and importers/remotes sync<br>
vs POST@v3/repository/UUID/<wbr>versions/<#nr>/<br>
<br>
  David proposes to namespace all objects under plug-in specific<br>
endpoints. This solves the repository--plug-in purity caveat, allows<br>
great plug-in flexibility and prevents endpoint name collisions.<br>
 This approach may allow the plug-ins UX to drift from each other<br>
though, and solves neither the multiple/no importers case, nor the<br>
scattering of repository versions creation endpoints and fails 2)&3).<br>
<br>
I believe this Master/Detail Tasks design to be a reasonable<br>
compromise on the requirements in 1) 2) 3).<br>
<br>
Cheers,<br>
milan<br>
<div class="HOEnZb"><div class="h5"><br>
On Wed, Mar 28, 2018 at 9:38 PM, Dennis Kliban <<a href="mailto:dkliban@redhat.com">dkliban@redhat.com</a>> wrote:<br>
> On Wed, Mar 28, 2018 at 12:20 PM, Ina Panova <<a href="mailto:ipanova@redhat.com">ipanova@redhat.com</a>> wrote:<br>
>><br>
>> I do not think that it's a valid argument to ban the proposal just because<br>
>> the proposal will bring changes to the existing plugins. Because:<br>
>><br>
>> 1) i think it would be fair to think of other plugins and find a solution<br>
>> all plugins will be happy with --> so we are back to the generic correctness<br>
>> problem<br>
>> 2) we are not GA, not even Beta, we are free and eligible to make changes,<br>
>> no promises made yet.<br>
>> 3) if we bring changes *this* exactly is the time to do because we have<br>
>> just 2 plugins working with basic functionality :)<br>
>><br>
>> W/r to the "Pulp turning into a task running system" ..and yet that's a<br>
>> system based on distributed task system<br>
><br>
><br>
> Pulp may rely on a tasking system to get work done, but we don't want users<br>
> thinking of it as a tasking system. We want our users to think of Pulp as a<br>
> repository management system.<br>
><br>
>><br>
>><br>
>> I suggest to organize a meeting with an agenda in advance that would list<br>
>> 1) concerns 2) questions<br>
>> I also think it would be valuable to hear Jeff's feedback.<br>
>><br>
>> If the team finds that meeting idea is beneficial with the believe that<br>
>> after the meeting we will:<br>
>> 1) i am not naive to believe that we would reach consensus but at least we<br>
>> would move forward<br>
>> 2) we will decrease the frustration level, because face2face conversation<br>
>> is more profitable, since we do see faces, have social interaction and not<br>
>> type onto keyboard and stare at the text on the monitor.<br>
>><br>
>> then...I will take the action item and schedule the meeting.<br>
>><br>
>> Meanwhile we'll have time to chew on Easter eggs and give to the proposal<br>
>> a deeper, unbiased, full of protein (that helps brain thinking) thought.<br>
>><br>
><br>
> I am against having a meeting to discuss this. The discussion on the list<br>
> has gotten traction and I'd like it to continue on here.<br>
><br>
>><br>
>><br>
>><br>
>><br>
>> --------<br>
>> Regards,<br>
>><br>
>> Ina Panova<br>
>> Software Engineer| Pulp| Red Hat Inc.<br>
>><br>
>> "Do not go where the path may lead,<br>
>>  go instead where there is no path and leave a trail."<br>
>><br>
>> On Wed, Mar 28, 2018 at 12:11 AM, Brian Bouterse <<a href="mailto:bbouters@redhat.com">bbouters@redhat.com</a>><br>
>> wrote:<br>
>>><br>
>>> In terms of removing POST /api/v3/repositories/<uuid>/<wbr>versions/ from<br>
>>> core, I want to bring it back to the MVP language and REST which drove the<br>
>>> original design. The MVP has: "As an authenticated user, I can create a new<br>
>>> version by adding or removing content to the latest version." To facilitate<br>
>>> that in a generic way, we need a core endpoint to do that, i.e.<br>
>>> /api/v3/repositories/<uuid>/<wbr>versions/. My concern is that removing it would<br>
>>> cause us to not fulfill our use cases without requiring more code from some<br>
>>> plugin writers. Also in terms of REST philosophy, POSTing to the<br>
>>> RespotoryVersion resource to create a new RepositoryVersion is the<br>
>>> traditional url design.<br>
>>><br>
>>> For pulp_ansible, for example, the generic add/remove functionality at<br>
>>> core endpoint ^ would be meet all of the pulp_ansible user's needs because<br>
>>> of the way the pulp_ansible content is modelled. So removing this endpoint<br>
>>> means more work for pulp_ansible developers w.r.t creating repo versions and<br>
>>> providing tasks and endpoints. I don't see this extra responsibility on<br>
>>> plugin writers coming with a clear benefit.<br>
>>><br>
>>> One idea I liked in this discussion is to have a documented convention<br>
>>> that encourages plugin writers to put their viewsets in a namespaced area.<br>
>>> They still need the ability to put them anywhere due to live API<br>
>>> goals/requirements so this would only be a convention for those tasks they<br>
>>> are offering directly to their users.<br>
>>><br>
>>><br>
>>><br>
>>><br>
>>><br>
>>> On Tue, Mar 27, 2018 at 5:40 PM, David Davis <<a href="mailto:daviddavis@redhat.com">daviddavis@redhat.com</a>><br>
>>> wrote:<br>
>>>><br>
>>>> I like Austin’s task proposal in that the plugin writers can focus on<br>
>>>> serializers and tasks that can be easily integrated with core. That said, I<br>
>>>> agree on the counterpoints raise about the new resource endpoints and<br>
>>>> turning much of pulp into a task running system. So I am a bit mixed on<br>
>>>> which approach is better.<br>
>>>><br>
>>>> I do think that we should remove POST<br>
>>>> /api/v3/repositories/<uuid>/<wbr>versions/ from core.<br>
>>>><br>
>>>><br>
>>>> David<br>
>>>><br>
>>>> On Tue, Mar 27, 2018 at 3:49 PM, Austin Macdonald <<a href="mailto:amacdona@redhat.com">amacdona@redhat.com</a>><br>
>>>> wrote:<br>
>>>>>><br>
>>>>>> /api/v3/repositories/<uuid>/<wbr>versions/ endpoint does not perform plugin<br>
>>>>>> specific validation which can lead to "broken" repository versions.<br>
>>>>>> Plugin authors don't have any convention to follow when creating<br>
>>>>>> custom REST API endpoints for creating repository versions.<br>
>>>>>> As a result of ^, a user will have a hard time identifying repository<br>
>>>>>> version creation APIs in different plugins.<br>
>>>>><br>
>>>>><br>
>>>>> I agree with these points.<br>
>>>>>><br>
>>>>>> My first inclination is to disable the ability to POST to<br>
>>>>>> /api/v3/repositories/<uuid>/<wbr>versions/ and require users to use the plugin<br>
>>>>>> specific APIs for creating repository versions. However, I think that<br>
>>>>>> integrators of build systems that produce a variety of content types would<br>
>>>>>> have a lot more flexibility if they could use a single generic API endpoint<br>
>>>>>> to create a repository version independent of the content type.<br>
>>>>>><br>
>>>>>> Let's continue this discussion by answering the following question:<br>
>>>>>><br>
>>>>>> Should we disable the ability to POST to<br>
>>>>>> /api/v3/repositories/<uuid>/<wbr>versions/ and require users to always use a<br>
>>>>>> plugin specific repository version creation API?<br>
>>>>><br>
>>>>> Yes, I think we should disable POST to<br>
>>>>> /api/v3/repositories/<uuid>/<wbr>versions/<br>
>>>>><br>
>>>>> Simplifying integration is important, but we should not sacrifice<br>
>>>>> correctness enforcement.<br>
>>>>><br>
>>>>> ______________________________<wbr>_________________<br>
>>>>> Pulp-dev mailing list<br>
>>>>> <a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
>>>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
>>>>><br>
>>>><br>
>>>><br>
>>>> ______________________________<wbr>_________________<br>
>>>> Pulp-dev mailing list<br>
>>>> <a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
>>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
>>>><br>
>>><br>
>>><br>
>>> ______________________________<wbr>_________________<br>
>>> Pulp-dev mailing list<br>
>>> <a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
>>><br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> Pulp-dev mailing list<br>
>> <a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
>><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> Pulp-dev mailing list<br>
> <a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
><br>
</div></div></blockquote></div><br></div>