[openstack-dev] [ara] Best practices on what to return from REST API ?

David Moreau Simard dms at redhat.com
Wed Aug 9 04:07:34 UTC 2017


So I'm making what I think is good progress towards the python and
REST API implementation for ARA but now I have a question.
I've made the following API "GET" endpoints:

- files (saved Ansible files)
- hosts (hosts involved in playbooks and their facts, if available)
- playbooks (data about the actual playbook and ansible parameters)
- plays (data about plays)
- results (actual results like 'ok', 'changed' as well as the data
from the Ansible module output)
- tasks (data about the task, like name, action and file path)

Each endpoint is self-sufficient and allows consumers to search
individual endpoints as required, for example:
(See attached links for actual and real output)

- GET /api/v1/plays # [1] List all plays
- GET /api/v1/plays?id=1 # [2] Get play with id 1
- GET /api/v1/plays?playbook_id=1 # [3] List all plays for playbook_id 1

The mechanism and logic is the same for all endpoints.
Where I get a bit doubtful is because some components have
relationships, like the following:

- files have file contents (file.content) [4]
- hosts have facts (host.facts) [5]
- tasks have results (task.results) [6]
- playbooks basically aggregate everything (playbook.files,
playbook.hosts, playbook.plays, playbook.results, playbook.tasks) so
it's potentially huge.

So, what is the best practice here ?
I'm thinking that returning all the available data on a LIST call (GET
/api/v1/playbooks) is nuts because of the potential amount of data

I'm torn between two different approaches but I would be happy to be
convinced there's a better way.

1) Only return "child" resources on specific call
So, when doing a GET on something that is expected to return a list
(GET /api/v1/playbooks), do not return child resources.
And, when doing a GET on the specific resource (GET
/api/v1/playbooks?id=1), display all the child resources.
This would be sort of analogous to how python-openstackclient has
different fields when doing "openstack server list" and "openstack
server show".

However, the amount of data for even a single playbook is likely very
significant at scale.

2) Require sub calls for different components
In this method, we would not return child resources when doing a list
call (GET /api/v1/playbooks) or when doing a specific call (GET
To get child resources, you would need to pick them up one by one, ex:

for playbook in playbooks:
   files = FileApi.get(playbook_id=playbook['id']
   hosts = HostApi.get(playbook_id=playbook['id']
   plays = PlayApi.get(playbook_id=playbook['id']

I feel like approach #2 would be best -- for running at scale but also
in the context of loading data asynchronously and concurrently.

Any opinions ?

Thanks !

[1]: http://paste.openstack.org/raw/617868/
[2]: http://paste.openstack.org/raw/617869/
[3]: http://paste.openstack.org/raw/617870/
[4]: http://paste.openstack.org/raw/617871/
[5]: http://paste.openstack.org/raw/617872/
[6]: http://paste.openstack.org/raw/617873/

David Moreau Simard
Senior Software Engineer | OpenStack RDO

dmsimard = [irc, github, twitter]

More information about the OpenStack-dev mailing list