New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OpenAPI/Swagger spec (fixes #631) #977
Conversation
There are two ways of creating a valid json api with openapi (swagger) support: 1.) swagger.yaml (use yaml, we need to read it) as master + some validation [1] Every way has its advantages and disadvantages. [1] https://github.com/pipermerriam/flex or https://github.com/striglia/pyramid_swagger |
@delijati, thank you for the feedback!
About YAML instead of JSON, I agree. It is listed as pending. |
For the class YamlRendererFactory(object):
def __init__(self, info):
pass
def __call__(self, value, system):
response = system['request'].response
response.headers['Content-Type'] = 'application/x-yaml; charset=UTF-8'
return yaml.dump(value).encode('utf-8')
def includeme(config):
config.add_renderer(
'yaml', 'pyramid_swagger.api.YamlRendererFactory'
) |
@delijati i've used validation of requests/responses just on tests. I think using it in production doesn't make much sense (as we already validate them using colander). The idea is only to ensure that the spec is correct, not use it for validation. |
As you mentioned that kinto is already using |
@gabisurita I hacked a small plugin together, check it out if you like. $ pip install git+https://github.com/delijati/kinto_swagger.git
$ vim config/kinto.ini
kinto.includes=kinto_swagger
$ firefox http://0.0.0.0:8888/v1/swagger |
@delijati I've tried the plugin, but got a Here's the traceback:
|
@gabisurita i tried it on the $ git clone https://github.com/Kinto/kinto.git
$ cd kinto
$ virtualenv env
$ env/bin/pip install -e .
$ env/bin/pip install git+https://github.com/delijati/kinto_swagger.git
$ kinto init
$ kinto migrate
$ vim config/kinto.ini
...
kinto.includes = kinto.plugins.default_bucket
kinto_swagger
...
$ kinto start
$ firefox http://0.0.0.0:8888/v1/swagger Btw. the error seams to be a older version of |
Upgrading
|
1. How should responses be documented? I think currently 2. Patch requests should have a body, but that doesn't show on the documentation Maybe the 3. How to document query strings? That is a class Query(MappingSchema):
yeah = SchemaNode(String())
mau = SchemaNode(String())
class RequestSchema(MappingSchema):
body = Body(description="Defines a cornice body schema")
querystring = Query() 4. Does it allows customizing the tags? I think putting all the operations under the tag buckets may be confusing, specially when using client generators. Currently it only does 5. How to set up authentication? You mean this? https://github.com/swagger-api/swagger-ui#header-parameters 6. Finally it doesn't seems to generate valid swagger, but I understand it's just a sketch. Never checked that ;) |
@delijati, great! We may wait for @glasserc, @Natim and @leplatrem to discuss this,but for now my impressions are:
|
0069e55
to
a4cf5eb
Compare
Sorry I wasn't able to look at this for so long!
Custom headers like If-Match and If-Not-Match weren't there when I looked at this earlier, but I see that they're now. In a meeting today, @gabisurita said that support for headers has just landed in Swagger 2.0. |
1b13119
to
9a1fbd7
Compare
27e7e62
to
26d122c
Compare
ceea4c2
to
60cf185
Compare
60cf185
to
9519ccd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This work is impressive, just a few nits.
Bravo 👍
client generation. | ||
|
||
.. important:: | ||
OpenAPI 2.0 currently doensn't some features that are present on Kinto API. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OpenAPI 2.0 currently doensn't some features that are present on Kinto API.
Do you mean:
OpenAPI 2.0 currently doesn't support some features that are present on Kinto API.
Also, :ref:`collection defined schemas <collection-json-schema>`, | ||
are not validated, So if you're using client | ||
generation, you may need to implement these features. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a note on how you choose to handle this limitations in the SWAGGER file?
``swagger.yaml`` file on the package root containing an OpenAPI extension | ||
for the main specification. You may use it to include additional resources | ||
that the plugin provides or override the original definitions. You may disable | ||
Swagger extensions by setting ``kinto.swagger_extensions`` to ``False`` on the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather have a default plugin then rather than yet another way to activate / deactivate features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that if you can deactivate it we probably need a capability for it.
Any reason why you want to be able to deactivate it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be unlikely, but I think it possible to have conflicts in plugins. But I think we can drop this keep it as a default, and reintroduce if we need it later. What do you think?
@@ -16,6 +16,7 @@ pyramid==1.7.3 | |||
pyramid-multiauth==0.9.0 | |||
pyramid-tm==1.1.1 | |||
python-dateutil==2.6.0 | |||
PyYAML==3.12 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use ruamel.yaml
rather than PyYAML
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also because we had this discussion for kinto-wizard and we made this choice there: https://github.com/Kinto/kinto-wizard/blob/master/setup.py
@@ -26,6 +27,7 @@ def read_file(filename): | |||
'jsonpatch', | |||
'python-dateutil', | |||
'pyramid_multiauth >= 0.8', # User on policy selected event. | |||
'PyYAML', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ruamel.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is certainly getting very close! I don't really understand why turning additionalProperties
from {"description": "blah"}
to {}
fixes anything. Could you do some investigation to figure out why this causes a bug and exactly where the bug is?
By default all includes on the configuration file will be prompt for a | ||
``swagger.yaml`` file on the package root containing an OpenAPI extension | ||
for the main specification. You may use it to include additional resources | ||
that the plugin provides or override the original definitions. You may disable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example might help here. We should at least say something like "These YAML files are merged recursively with the Kinto swagger.yaml file".
# Include securityDefinitions that are not on default security | ||
for name, prop in auth_types.items(): | ||
# include securityDefinitions that are not on default security options | ||
for name, prop in security_defs.items(): | ||
security_def = {name: prop.get('scopes', {}).keys()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think some more comments would be helpful here to readers who don't already know much about the OpenAPI spec. How about: The 'security' field lists all acceptable ways of authenticating, so no plugin should add something to 'securityDefinitions' without it being here too
, and then A 'security' requirement is an object of the form {security_mechanism: ['list', 'of', 'oauth2', 'scopes']} # or an empty list if oauth2 isn't used
.
on the default error message. | ||
4. [Collection schemas](http://kinto.readthedocs.io/en/stable/api/1.x/collections.html#collection-json-schema) | ||
can be provided when defining a collection and should be a valid JSON Schema object, | ||
but this is not validated by this specification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should unify this list of limitations with the ones in the documentation, and provide a link to them.
OpenAPI 2.0 currently doensn't some features that are present on Kinto API. | ||
Some known limitations are | ||
lack of validation on or clauses (e.g. provide `data` or `permissions` in PATCH | ||
operations), no support for non schema querystrings, as used on :ref:`filtering <filtering>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, and provide request or default in /batch requests
Also, I'd like to see a comment about whatever we ended up doing with additionalProperties and what bugs that fixes in what libraries, etc.
GET /swagger.json | ||
================= | ||
|
||
Returns the OpenAPI specification for the running instance of Kinto on JSON format. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also make a note that this is the ONLY supported way to get the spec, since the running code does some transformations on the data, for example updating the host and listing the accepted security mechanisms.
lack of validation on or clauses (e.g. provide `data` or `permissions` in PATCH | ||
operations), no support for non schema querystrings, as used on :ref:`filtering <filtering>` | ||
with additional fields, and no optional response headers, as required for | ||
`Backoff signs`<http://kinto.readthedocs.io/en/stable/api/1.x/backoff.html>`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something got messed up with your RST here. I think you have an extra backtick before your link. You might also need an underscore after the closing backtick.
In terms of logic that's super weird, but following the traceback for the error, unmarshal_model, has a special case for empty objects, which skips unmarshal_object, that explicitly checks for type. So there's a indeed a special case to handle empty objects. We may call it a bug on bravado, but at this point I don't really know where the bug is... ¯\(ツ)/¯
|
949a562
to
0bd3081
Compare
OK, I'm r+ on this. @Natim @leplatrem ? |
I'm in favor of merging it too! There's one little detail that we discussed recently: the URL In Shavar @tarekziade used the URL I don't want to delay the merging of this PR, but if you agree we can create an issue and think about it before we release the next Kinto version :) Congrats! |
I agree. According to spec, there's still a convention in using |
@@ -0,0 +1,65 @@ | |||
import unittest | |||
import mock | |||
import yaml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have to change this to ruamel.yaml
now that we've updated the dependency? Sorry if this is a stupid question, I've never used ruamel.yaml
before...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should. This should have raised on tests, but I guess there's another package that imports pyYAML.
8a7ac47
to
250e78d
Compare
🎊 |
Fixes #631
Features:
/v1/swagger.json
Limitations:
(ex: id doesn't show as a required field), doing so would result in two different
object definitions for each object, which would add unnecessary complexity to the clients IMO)
Pending:
test_resources
)r? @glasserc @Natim @leplatrem