-
Notifications
You must be signed in to change notification settings - Fork 62
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
[PROPOSAL] Evolving the API Spec repo #80
Comments
I'm late to this proposal, would only say that "Translate Smithy Spec to OpenAPI spec for every commit." sounds like a "build and release" to me. Maybe it's helpful to think of it that way? |
With the move toward native openAPI, the only relevant piece is validating the OpenAPI spec, which I'm working on right now. |
Is validating and linting the same thing? If so this issue can be closed to avoid duplicating with #22? |
Yes, they are the same. Closing. |
This repo was created to define accurate specs for OpenSearch APIs, and from there, generate OpenSearch clients in different languages. This will keep all clients in sync, and it will let us deploy changes in the API to all clients. With that in mind, there are 3 goals:
As explained further below, I propose the following four-stage process that, on its surface may appear complex, but which eliminates unnecessary effort and achieves the above goals:
The Challenges
The OpenSearch API does not follow REST API constraints and conventions
In REST API, each endpoint represents a resource in a hierarchy of resources, and the HTTP verbs are mapped to CRUD actions to interact with said resource. Hypothetically, to create or update an OpenSearch document we would have the following endpoints and operations in the classic REST API fashion:
However, we currently have the following document operations on OpenSearch:
As you can see, OpenSearch uses different endpoints to interact with the same resource, a document in this example, (instead of one endpoint with different HTTP verbs/operations). Moreover, different HTTP verbs like, PUT and POST, have the exact same meaning on the same endpoints.
This causes issues for off-the-shell client generators:
POST /{index}/_update/{id}
, for example, will be translated to a method namedpost_index_update_id
. That is confusing! Without reading the description, it’s impossible to tell if the method will create a new document (post
) or modify an existing document (update
).Namespace and the grouping of operations by functionality
OpenSearch API operations are grouped into API methods by functionality, and these methods are then grouped into namespaces. Consider the following operations:
In OpenSearch clients, these two operations are combined into one method called
shards
where{index}
is an optional path parameter. The shards method belongs to a namespace called cat. And to invoke this method:client.cat.shards(index: 'books')
This operation grouping is also reflected in Elasticsearch’s legacy spec. Take a look at this excerpt of the legacy
index.json
spec file:This spec describes 3 different operations in 2 different URL paths, but they are considered one action with shared description, query parameters, path parameters (where
{index}
is required but{id}
is optional), and request body.For more information on this topic, check out this issue.
Solutions
Generate Clients from OpenAPI Spec
We have had a long discussion on whether to generate the clients from OpenAPI or Smithy Spec. The consensus is that OpenAPI is an industry standard. Many developers are familiar with OpenAPI and have experience working with it. OpenAPI is well supported by most IDEs, with a large set of tools, especially Swagger, built for it over the years.
The generators for OpenAPI spec can be reused to generate clients for OpenSearch Extensions. Many of these extensions will be developed by independent teams who will likely use OpenAPI to describe their APIs. This is one reason not to simply use the legacy spec to generate client code, even though the spec was built around unique traits of OpenSearch API.
One thing to keep in mind: Any generator we write must have the ability to combine many operations into one action. It’s not as simple as translating the spec of an operation to an API method. We have already written a prototype generator that can handle a few types of operation combinations (Get-Get, Post-Put, Post-Get, ...) in Ruby.
While both OpenAPI and Smithy offer off-the-shelf generators that can generate brand new clients with the push of a button, they are meant for conventional REST APIs, which is not the case with OpenSearch, as explained above. The API methods generated from such generators will be very confusing to use, and cannot be retrofitted into existing clients. We will have to write our own generators regardless. So, neither Smithy nor OpenAPI has the advantage over the other in this regard.
Use Smithy as a tool to write OpenAPI Spec
Even with tools that help navigate and edit OpenAPI docs, writing specs for over 300 operations in JSON or YAML is still a daunting task. Moreover, since OpenAPI does not allow reference by operation, OpenSearch operations serving the same purpose are scattered in different places and get mixed up with other operations.
Smithy, on the other hand, comes with features that make it easier to maintain an API spec as complex as the OpenSearch API:
With that being said, we will only use Smithy as a tool to write OpenAPI spec. That means:
Implementation Details
Fill in missing meta data for client generators
The core OpenAPI does not support namespace and operation grouping. We can address this by adding our own OpenAPI extension to include this info in each API operation. For example:
x-operation-group: cat.shards
x-operation-group: index
And to support incremental client generation (where we only need the client generators to generate code for new operations), we will add extensions delineating when an operation was added, deprecated, and removed:
x-version-added: 0.7
x-version-deprecated: 1.5
x-version-removed: 2.0
Smithy’s custom traits are the equivalent of OpenAPI extensions. At the time of this writing, the native Smithy-to-OpenAPI converter does not translate Smithy traits to OpenAPI extensions. However, we have a solution for this, and we’re working on upstreaming this change to the converter.
Backfill existing operations
Github Workflows
For more details, check out the related proposal.
Conclusion
The four-stage process addresses the many quirks of the OpenSearch API. It allows us to rapidly flesh out the API definition using the legacy spec. It allows us to fill in the missing pieces efficiently using Smithy, which is a well-factored way of maintaining specs. By converting the Smithy spec to OpenAPI, we can take advantage of the OpenAPI ecosystem and keep the door open to new developers to contribute to clients.
I welcome feedback on this proposal.
The text was updated successfully, but these errors were encountered: