<div dir="ltr">I'm concerned that this conversation is too broad. I'm willing to brainstorm ideas because this is an important topic, but I also hope that at some point we can come back to the proposal for master/detail tasks.<div><br></div><div>This idea is interesting, because it provides a novel way to connect the plugins to pulpcore calls. The views that plugins implement would not be normal views, they would operate more like OPTIONS schema views. I'll try to show how I think this would look from a user's perspective:</div><div><br></div><div><u>File Sync:</u></div><div><u><br></u></div><div>The user doesn't know how to sync, so they do a GET request:</div><div><b>GET /v3/versionactions/</b></div><div><b><br></b></div><div>This returns a list of possible actions, one of them being v3/versionactions/file/sync. To see how to use that they do another GET request:</div><div><b>GET /v3versionactions/file/sync/</b></div><div><u><br></u></div><div>This returns the description of the file-sync action and the parameters necessary (importer, repository)</div><div><u><br></u></div><div><b>POST v3/repositories/1234/versions/</b> importer=importer_href, repository=repository_href, action=v3/versionactions/file/sync/<br></div><div><br></div><div>I have some practical questions:</div><div><ul><li>What does the documentation for v3/repositories/1234/versions/ look like?</li><ul><li>Are the parameters listed, or does the user have to use v3/versionactions/sync/ to retrieve their schema?</li></ul><li>How does the RepositoryVersionsViewSet use the versionaction?</li><ul><li>How are the params `importer`, and `repository` validated? </li><ul><li>Synchronously</li><li>Asynchronously</li></ul><li>How is the celery task connected and dispatched?</li></ul></ul><div>Here are my initial thoughts:</div></div><div><ul><li>I like that this brings us back to "to create a new RepositoryVersion, POST to versions". </li><ul><li>I especially like that all versions are created at a single endpoint.</li></ul><li>I don't like that the plugins are creating views that are not intended to be used as endpoints. These views are only "hit" for documentation, and they are used as parameters to other tasks.<br></li><ul><li>This could be confusing for users</li><li>This is a different type of work than the rest of plugin writing, so it will have its own learning curve</li><li>This would not (speculation) play nice with auto-documentation. The autodocumentation would not know about the possible parameters for the actions, so the users would have to user GET v3/versionactions/ <i>instead </i>of docs.</li><li>This would not <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:left;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">(speculation)<span> </span></span>play nice with auto-bindings and clients. Same problem as ^</li><li>GET request does not retrieve objects, it retrieves schema</li></ul></ul></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 2, 2018 at 10:26 AM, Dennis Kliban <span dir="ltr"><<a href="mailto:dkliban@redhat.com" target="_blank">dkliban@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><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><b>pulpcor<wbr>e/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/" target="_blank">http://localhost/api/v3/<wbr>versionactions/pulpcore/<wbr>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><b>plugin<wbr>>/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/" target="_blank">http://localhost/api/v3/<wbr>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><b>pl<wbr>ugin>/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/" target="_blank">http://localhost/api/v3/<wbr>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>/<wbr>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="HOEnZb"><div class="h5"><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>/[sync<wbr>s, 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>/versi<wbr>ons/<#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>/[<cu<wbr>stom 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/[importer<wbr>s, 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_versio<wbr>n"<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/versio<wbr>ns/<#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="m_-6736672718274711553HOEnZb"><div class="m_-6736672718274711553h5"><br>
On Wed, Mar 28, 2018 at 9:38 PM, Dennis Kliban <<a href="mailto:dkliban@redhat.com" target="_blank">dkliban@redhat.com</a>> wrote:<br>
> On Wed, Mar 28, 2018 at 12:20 PM, Ina Panova <<a href="mailto:ipanova@redhat.com" target="_blank">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" target="_blank">bbouters@redhat.com</a>><br>
>> wrote:<br>
>>><br>
>>> In terms of removing POST /api/v3/repositories/<uuid>/ve<wbr>rsions/ 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>/ve<wbr>rsions/. 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" target="_blank">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>/ve<wbr>rsions/ 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" target="_blank">amacdona@redhat.com</a>><br>
>>>> wrote:<br>
>>>>>><br>
>>>>>> /api/v3/repositories/<uuid>/ve<wbr>rsions/ 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>/ve<wbr>rsions/ 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>/ve<wbr>rsions/ 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>/ve<wbr>rsions/<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" target="_blank">Pulp-dev@redhat.com</a><br>
>>>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman<wbr>/listinfo/pulp-dev</a><br>
>>>>><br>
>>>><br>
>>>><br>
>>>> ______________________________<wbr>_________________<br>
>>>> Pulp-dev mailing list<br>
>>>> <a href="mailto:Pulp-dev@redhat.com" target="_blank">Pulp-dev@redhat.com</a><br>
>>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman<wbr>/listinfo/pulp-dev</a><br>
>>>><br>
>>><br>
>>><br>
>>> ______________________________<wbr>_________________<br>
>>> Pulp-dev mailing list<br>
>>> <a href="mailto:Pulp-dev@redhat.com" target="_blank">Pulp-dev@redhat.com</a><br>
>>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman<wbr>/listinfo/pulp-dev</a><br>
>>><br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> Pulp-dev mailing list<br>
>> <a href="mailto:Pulp-dev@redhat.com" target="_blank">Pulp-dev@redhat.com</a><br>
>> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman<wbr>/listinfo/pulp-dev</a><br>
>><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> Pulp-dev mailing list<br>
> <a href="mailto:Pulp-dev@redhat.com" target="_blank">Pulp-dev@redhat.com</a><br>
> <a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman<wbr>/listinfo/pulp-dev</a><br>
><br>
</div></div></blockquote></div><br></div>
</div></div><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></blockquote></div><br></div>