Skip to content
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

Rest API version compatibility #51816

Closed
jakelandis opened this issue Feb 3, 2020 · 11 comments
Closed

Rest API version compatibility #51816

jakelandis opened this issue Feb 3, 2020 · 11 comments

Comments

@jakelandis
Copy link
Contributor

jakelandis commented Feb 3, 2020

Systems/clients that wish to interact with Elasticsearch are required to do so over the REST API. Breaking changes to the REST API (in major versions) can introduce challenges for these systems/clients.

The preferred upgrade path is 1) upgrade Elasticsearch 2) upgrade the systems/clients that are interacting with Elasticsearch. However, major version upgrades are more likely 1) upgrade systems/clients to be compatible with the next major version of Elasticsearch 2) upgrade Elasticsearch. Upgrading the systems/clients that interact with Elasticsearch before upgrading Elasticsearch can create an high orchestration upgrade event. The administrators of Elasticsearch need to know that all systems that interact with Elasticsearch are compatible with the new major version before they can upgrade.

Rest API version compatibility seeks to address better de-coupling of systems/clients and server upgrades. Rest API version compatibility will ensure that requests and responses that worked in the prior major version will continue to function in the next major version without error (but may behave differently). The intent is to allow Administrators to upgrade the Elasticsearch server to new major versions without requiring (or at least minimal) changes to the systems/clients that talk to Elasticsearch. Further, Rest API version compatibility will not require specific deployment architectures or complex configuration. Rest API version compatibility will be enabled/disabled per HTTP request via an HTTP header.

Rest API version compatibility can be defined along two axis: 1) shape 2) behavior.

Shape

Shape is being defined as the structure of the HTTP request. Shape includes the JSON body for the request/response, the HTTP verb (GET, POST, etc.), the HTTP path (/foo/bar), HTTP parameters (?foo=bar), etc. Changes to the shape of request and responses (with minor exception) will be covered by REST API version compatibility.

For example, in 8.0 REST paths that started _xpack will no longer be available and will be replaced with a similar path but without the _xpack in the URL. If a system/client relied upon any of those URLs with _xpack in the path, those systems/clients would need to be upgraded prior to upgrading Elasticsearch from 7.x to 8.x.

With Rest API version compatibility (assuming it was requested via the header), those paths will still be honored since they were valid in 7.x. Any shape honored in 7.x will be honored in 8.x when Rest API version compatibility is requested. The request header that enables Rest API version compatibility can be requested to be compatible with a specific major version, for example, a request can request compatibility with v7. When Elasticsearch server is running 7.x and compatibility is requested for v7, the header will essentially be ignored. However, as soon as Elasticsearch is upgraded (from 7.x to 8.x) and the system/client is still sending a header requesting compatibility with v7, the 8.x server will read that header and ensure that any shape elements that worked in 7.x will continue to work in 8.x. This type of compatibility is a close cousin to traditional wire or binary compatibility.

For these shape based breaking changes across major versions, Rest API version compatibility allows the server to be upgraded independently to any required changes for the client.

Behavior

Rest API version compatibility as described here is distinctly different then most SAAS version-ed APIs. SAAS offerings can allow for stronger guarantees for how a service behind the version of REST API behaves then software you can download and run yourself. With Rest API version compatibility, the shape of the REST API (with minor exception) will be guaranteed to be compatible with the previous minor version, however, the behavior of the server may differ from the last prior major version.

For example, the default number of shards per index was changed in major version. Had Rest API version compatibility existed then it would have no impact on that change since that change was strictly about how Elasticsearch behaves. Many changes across majors (and minors) are changes to the behavior of the service and will be not influenced by REST API version compatibility.

Another example is that in 8.0 many of the deprecated discovery.zen are removed since a new cluster coordination subsystem was implemented in 7.x and the old one will be completely removed in 8.0. Since cluster coordination (and the related settings) is a behavior, not an REST API, it is not part Rest API version compatibility.

Shape && Behavior

Quite often shape and behavior change go hand-in-hand. Not all changes to the shape are as simple as a changing URL. Many of the breaking changes to the REST API also include some form of behavior change as well.

For 8.0 the most notable change that encompasses both shape and behavior is the complete removal of types. In versions prior to 8.0, many REST APIs supported the concept of a type within an index. 6.x and 7.x deprecated all functionality related to types, so that in 8.0 types will be completely removed. However, many REST API shape elements in 7.x are tightly correlated to the concept of a type. For example, in 7.x you could create an index with a custom type (e.g. PUT foo/custom_type/1 { "a" :"b"}). While that functionality is deprecated in 7.x, it is still supported in 7.x. However in 8.0, how can we still support the type based URLs for Rest API version compatibility if types will be completely removed ?

A form of behavior compatibility will be introduced on a case-by-case basis. Behavior compatibility’s primary focus is to best-effort honor the intent of the request and response and provide shape compatibility. In most cases behavior compatibility will not be identical to the prior version.

For the complete removal of types, the behavior compatibility strategy will be to internally map any type based request to a typeless based request. For example, (if compatibility is requested) the server will still accept typed based request (e.g. PUT foo/custom_type/1 { "a" :"b"}), but will internally convert to a typeless request (e.g. PUT foo/_doc/1 { "a" :"b"}). The goal here is to ensure that the requested shape is still compatible, honoring the intent of the request, but not behave exactly as it did in the prior version.

The behavior compatibility will be best effort to honor the intent of the request and preserve the format of the response. However, this will not always be sufficient for all use cases. In the above example, if the application logic was dependent on custom_type the behavior compatibility would not be sufficient. The service/client will still need to upgrade prior to Elasticsearch for those use-cases. Since compatibility will be requested per HTTP request via a header, clients can opt-out or opt-in per request.

The documentation will be updated to help clearly identify exactly how the behavior compatibility will be achieved to allow consumers better understand if compatibility will work for their use cases.

Deprecations and Compatibility

Elasticsearch follows a pattern of only introducing breaking changes in major release (with very few exceptions). All breaking changes are deprecated in a major version before they are implemented in the next major version. Rest API version compatibility will not change any of the existing deprecation or release strategies. However, Rest API version compatibility will extend the ability to use deprecated API for a full extra major release if (and only if) REST compatibility is requested for that API and version. Also, note that due the the case-by-case of behavior compatibility, the behavior that backs the REST API may not be sufficient for all use cases.

Additionally, a new type of warning will be introduced. A compatibility warning, much like the deprecation warnings will be introduced to help systems/clients understand where and what REST API version compatibility is doing. REST API version compatibility should be viewed as a compatibility layer to help systems/clients decouple their upgrade life-cycles for each other. It is not a long term strategy to keep using deprecated features.

Scope

Rest layer wire compatibility, but not behavior compatibility.

Duration

~ 12 months

List of high level tasks

TODO

Parking lot (things discussed, but need to revisit)

[ ] The relationship between Accept and Content-Type headers with/out compatibility. see #53228 (comment) PR to address this

@jakelandis
Copy link
Contributor Author

reserving first comment for additional information

@philkra
Copy link
Contributor

philkra commented Feb 4, 2020

pinging @elastic/es-clients

pgomulka added a commit that referenced this issue Mar 25, 2020
Providing a REST infrastructure to handle compatible APIs. Rest APIs that were removed in 8 will be available only if an HTTP request had a compatible header. At the moment is is expecting an Accept header to contain application/vnd.elasticsearch+json;compatible-with=7. This might be changed though when #52370 is resolved.
The REST changes contain

enriching RestRequest with a parameter Compatible-With. The value is taken from Accept header. See RestRequest creation. Used when deciding if a request to a compatible handler can be dispatched. See RestController.
//TODO this at the moment can be simplified to only use a value from a header. However in rest layer we often have only access to Params, so headers won't be accessible when implementing some compatible code

enriching XContentBuilder with a compatible version value. See AbstractRestChannel. Used when shape of a response is changed. see DocWriteResponse and GetResult

MediaType parsing change - see XContentType. because we expect a different media type now application/vnd.elasticsearch+json;compatible-with=7 (when previously application/json or similar)

testing changes - compat tests will have a compatible header set. see AbstractCompatRestTest.java

Compatible rest handlers - based on RestIndexAction and RestGetAction. See modules/rest-compatibility. These extend already existing handlers and register them in a RestCompatPlugin under a typed paths. They will only be accessible when a compatible header is present (use of compatibilityRequired method from RestHandler interface)

Without this PR 283 tests from 7.x are failing. - rest api spec tests only
with this PR 228 tests are passing - with almost all tests from index/* package passed (missing 2 tests that require change for include_type_param, to be added in a new PR)

relates #51816
@Musfiqur01
Copy link

Will this be available in ES 8? Does it mean that from ES 7 and onwards, we don't have to think about breaking Rest Api during the upgrade?

@pgomulka
Copy link
Contributor

@Musfiqur01 yes it will be available in ES8 accepting version 7 requests. This will allow you to upgrade your server first and your application with a client later. You will have to deal with breaking changes during your application upgrade.
API compatibility will only allow previous major version requests (ES8 accepting version 7 requests)

pgomulka added a commit that referenced this issue Oct 5, 2020
Content-Type and Accept headers can be populated with a versioned form of media types
like application/vnd.elasticsearch+json;compatible-with=7
when previously it was simple application/json or (cbor, yaml..) - this is still supported.
Extending MediaTypeParser to validate the parameters.

relates  #51816
pgomulka added a commit that referenced this issue Nov 5, 2020
Per REST endpoint media types declaration allows to make parsing/validation more strict.

If a media type was declared only in one endpoint (for instance CSV in SQL endpoint) it should not be allowed to parse that media type when using other endpoints.
However, the Compatible API need to be able to understand all media types supported by Elasticsearch in order to parse a compatible-with=version parameter.
This implies that endpoints need to declare which media type they support and how to parse them (if introducing new media types - like SQL).

How to parse:
MediaType interface still serves as an abstraction on top of XContentType and TextFormat. It also has a declaration of mappings String-MediaType with parameters. Parameters declares the names of parameters and regex to validate its values.
This instructs how to perform the parsing. For instance - XContentType.JSON has the mapping of application/vnd.elasticsearch+json -> JSON and allows parameters compatible-with=\d and charset=utf-8

MediaTypeParser was simplified into ParsedMediaType class with static factory method for parsing.

How to declare:
RestHandler interface is extended with a validAcceptMediaTypes which returns a MediaTypeRegistry - a class that encapsulates mappings of string (type/subtype) to MediaType, allowed parameters and formatPathParameter values.
We only need to allow of declaration of valid media types for Accept header. Content-Type valid media types are fixed to XContentType instances - json, yaml, smile, cbor.

relates #51816
pgomulka added a commit to pgomulka/elasticsearch that referenced this issue Nov 5, 2020
Per https://tools.ietf.org/html/rfc7231#section-3.1.1.1 MediaType can
have spaces around parameters pair, but do not allow spaces within
parameter. That means that parameter pair forbids spaces around `=`

follow up after
elastic#64406 (comment)
relates elastic#51816
pgomulka added a commit that referenced this issue Nov 6, 2020
Per https://tools.ietf.org/html/rfc7231#section-3.1.1.1 MediaType can
have spaces around parameters pair, but do not allow spaces within
parameter. That means that parameter pair forbids spaces around =

follow up after
#64406 (comment)
relates #51816
pgomulka added a commit to pgomulka/elasticsearch that referenced this issue Nov 6, 2020
Browsers are sending media ranges with quality factors on Accept header.
We should ignore the value and responde with applicaiton/json

closes elastic#64689
relates elastic#51816
pgomulka added a commit that referenced this issue Aug 5, 2021
The support for this lenient behaviour was removed in #41011
however since this is a change that affects a request shape it should
still be available to use it in rest api compatibility

relates #51816
pgomulka added a commit that referenced this issue Aug 5, 2021
previously removed in #42809. nested_path and nested_filter sort options will now throw exceptions suggesting to use nested option
relates #51816
pgomulka added a commit that referenced this issue Aug 5, 2021
…75896)

Previously removed in #42654. The query and the parameter won't work under rest api compatibility and an exception with a message is returned advising that just use of match/multi_match is enough

relates #51816
pgomulka added a commit to pgomulka/elasticsearch that referenced this issue Aug 5, 2021
v7compatibilityNotSupportedTests was introduced to make it easier to
track tests that have been identified as not needing compatible changes
and those that still need to be checked.
We have checked all tests now and the separate list is no longer needed.

relates elastic#51816
relates elastic#73912
pgomulka added a commit that referenced this issue Aug 19, 2021
v7compatibilityNotSupportedTests was introduced to make it easier to
track tests that have been identified as not needing compatible changes
and those that still need to be checked.
We have checked all tests now and the separate list is no longer needed.

relates #51816
relates #73912
droberts195 added a commit to droberts195/elasticsearch that referenced this issue Sep 7, 2021
Related to elastic#51816 / elastic#68905.

Adds back the _xpack/ml routes when using rest compatibility for a request.
droberts195 added a commit that referenced this issue Sep 14, 2021
Related to #51816 / #68905.

Adds back the _xpack/ml routes when using rest compatibility for a request.
@kid1412621
Copy link

How can I disable this in latest Java client?

@pgomulka
Copy link
Contributor

@kid1412621 why do you want to disable it?

Rest api compatibility is a server feature that is used when an old client is used against new server (v8 server vs v7 client).
Client is triggering it by sending application/vnd.elasticsearch+json;compatible-with=7 media type on Content-Type and/or Accept headers.

You can disable this in your client by using RestHighLevelClientBuilder#setApiCompatibilityMode .

@kid1412621
Copy link

@kid1412621 why do you want to disable it?

Rest api compatibility is a server feature that is used when an old client is used against new server (v8 server vs v7 client).
Client is triggering it by sending application/vnd.elasticsearch+json;compatible-with=7 media type on Content-Type and/or Accept headers.

You can disable this in your client by using RestHighLevelClientBuilder#setApiCompatibilityMode .

'Coz I'm using 7.10 on the server side, it seems not support this header.

@pgomulka
Copy link
Contributor

pgomulka commented Dec 23, 2021

@kid1412621 good point! The ability to parse .vnd.elasticsearch media types was added to ES 7.10 #65362 Whereas support for sending that media type is from HLRC v7.16

Looks like you are using a newer client than a server?

@kid1412621
Copy link

@kid1412621 good point! The ability to parse .vnd.elasticsearch media types was added to ES 7.10 #65362 Whereas support for sending that media type is from HLRC v7.16

Looks like you are using a newer client than a server?

Yeah,client: 7.16. server: 7.10.
I followed this to setup and use ElasticsearchClient.
I'll try the method u offered. Thx

@kid1412621
Copy link

kid1412621 commented Dec 24, 2021

RestHighLevelClientBuilder#setApiCompatibilityMode

Hi there, it seems there is no RestHighLevelClientBuilder#setApiCompatibilityMode under The Elasticsearch Java API Client(not HLRC).

@jakelandis
Copy link
Contributor Author

This will be included in 8.0 of Elasticsearch.

jrodewig added a commit that referenced this issue Feb 8, 2022
Adds a release highlight for the 7.x REST API compatibility headers.

Relates to #51816 and #83487
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants