Skip to content

Commit 7564c34

Browse files
author
Tim Bannister
committed
Merge removal of product verification with later 7.x changes
2 parents 72ed239 + c4a9ba5 commit 7564c34

File tree

8 files changed

+9
-915
lines changed

8 files changed

+9
-915
lines changed

elasticsearch/_async/transport.py

Lines changed: 1 addition & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,16 @@
1818
import asyncio
1919
import logging
2020
import sys
21-
import warnings
2221
from itertools import chain
2322

2423
from ..exceptions import (
25-
AuthenticationException,
26-
AuthorizationException,
2724
ConnectionError,
2825
ConnectionTimeout,
2926
ElasticsearchWarning,
3027
SerializationError,
3128
TransportError,
3229
)
33-
from ..transport import Transport, _ProductChecker
30+
from ..transport import Transport
3431
from .compat import get_running_loop
3532
from .http_aiohttp import AIOHttpConnection
3633

@@ -117,10 +114,6 @@ async def _async_init(self):
117114
self.loop = get_running_loop()
118115
self.kwargs["loop"] = self.loop
119116

120-
# Set our 'verified_once' implementation to one that
121-
# works with 'asyncio' instead of 'threading'
122-
self._verify_elasticsearch_lock = asyncio.Lock()
123-
124117
# Now that we have a loop we can create all our HTTP connections...
125118
self.set_connections(self.hosts)
126119
self.seed_connections = list(self.connection_pool.connections[:])
@@ -335,14 +328,6 @@ async def perform_request(self, method, url, headers=None, params=None, body=Non
335328
method, headers, params, body
336329
)
337330

338-
# Before we make the actual API call we verify the Elasticsearch instance.
339-
if self._verified_elasticsearch is None:
340-
await self._do_verify_elasticsearch(headers=headers, timeout=timeout)
341-
342-
# If '_verified_elasticsearch' isn't 'True' then we raise an error.
343-
if self._verified_elasticsearch is not True:
344-
_ProductChecker.raise_error(self._verified_elasticsearch)
345-
346331
for attempt in range(self.max_retries + 1):
347332
connection = self.get_connection()
348333

@@ -414,84 +399,3 @@ async def close(self):
414399

415400
for connection in self.connection_pool.connections:
416401
await connection.close()
417-
418-
async def _do_verify_elasticsearch(self, headers, timeout):
419-
"""Verifies that we're connected to an Elasticsearch cluster.
420-
This is done at least once before the first actual API call
421-
and makes a single request to the 'GET /' API endpoint and
422-
check version along with other details of the response.
423-
424-
If we're unable to verify we're talking to Elasticsearch
425-
but we're also unable to rule it out due to a permission
426-
error we instead emit an 'ElasticsearchWarning'.
427-
"""
428-
# Ensure that there's only one async exec within this section
429-
# at a time to not emit unnecessary index API calls.
430-
async with self._verify_elasticsearch_lock:
431-
432-
# Product check has already been completed while we were
433-
# waiting our turn, no need to do again.
434-
if self._verified_elasticsearch is not None:
435-
return
436-
437-
headers = {
438-
header.lower(): value for header, value in (headers or {}).items()
439-
}
440-
# We know we definitely want JSON so request it via 'accept'
441-
headers.setdefault("accept", "application/json")
442-
443-
info_headers = {}
444-
info_response = {}
445-
error = None
446-
447-
attempted_conns = []
448-
for conn in chain(self.connection_pool.connections, self.seed_connections):
449-
# Only attempt once per connection max.
450-
if conn in attempted_conns:
451-
continue
452-
attempted_conns.append(conn)
453-
454-
try:
455-
_, info_headers, info_response = await conn.perform_request(
456-
"GET", "/", headers=headers, timeout=timeout
457-
)
458-
459-
# Lowercase all the header names for consistency in accessing them.
460-
info_headers = {
461-
header.lower(): value for header, value in info_headers.items()
462-
}
463-
464-
info_response = self.deserializer.loads(
465-
info_response, mimetype="application/json"
466-
)
467-
break
468-
469-
# Previous versions of 7.x Elasticsearch required a specific
470-
# permission so if we receive HTTP 401/403 we should warn
471-
# instead of erroring out.
472-
except (AuthenticationException, AuthorizationException):
473-
warnings.warn(
474-
(
475-
"The client is unable to verify that the server is "
476-
"Elasticsearch due security privileges on the server side"
477-
),
478-
ElasticsearchWarning,
479-
stacklevel=4,
480-
)
481-
self._verified_elasticsearch = True
482-
return
483-
484-
# This connection didn't work, we'll try another.
485-
except (ConnectionError, SerializationError, TransportError) as err:
486-
if error is None:
487-
error = err
488-
489-
# If we received a connection error and weren't successful
490-
# anywhere then we re-raise the more appropriate error.
491-
if error and not info_response:
492-
raise error
493-
494-
# Check the information we got back from the index request.
495-
self._verified_elasticsearch = _ProductChecker.check_product(
496-
info_headers, info_response
497-
)

elasticsearch/compat.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,6 @@ def to_bytes(x, encoding="ascii"):
7070
except (ImportError, AttributeError):
7171
pass
7272

73-
try:
74-
from threading import Lock
75-
except ImportError: # Python <3.7 isn't guaranteed to have threading support.
76-
77-
class Lock:
78-
def __enter__(self):
79-
pass
80-
81-
def __exit__(self, *_):
82-
pass
83-
8473

8574
__all__ = [
8675
"string_types",

elasticsearch/exceptions.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ class UnsupportedProductError(ElasticsearchException):
5656
it's not connected to a supported product.
5757
"""
5858

59-
6059
class TransportError(ElasticsearchException):
6160
"""
6261
Exception raised when ES returns a non-OK (>=400) HTTP status code. Or when

elasticsearch/transport.py

Lines changed: 4 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,14 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
import re
1918
import time
20-
import warnings
2119
from itertools import chain
2220
from platform import python_version
2321

2422
from ._version import __versionstr__
25-
from .compat import Lock
2623
from .connection import Urllib3HttpConnection
2724
from .connection_pool import ConnectionPool, DummyConnectionPool, EmptyConnectionPool
2825
from .exceptions import (
29-
AuthenticationException,
30-
AuthorizationException,
3126
ConnectionError,
3227
ConnectionTimeout,
3328
ElasticsearchWarning,
@@ -404,14 +399,6 @@ def perform_request(self, method, url, headers=None, params=None, body=None):
404399
method, headers, params, body
405400
)
406401

407-
# Before we make the actual API call we verify the Elasticsearch instance.
408-
if self._verified_elasticsearch is None:
409-
self._do_verify_elasticsearch(headers=headers, timeout=timeout)
410-
411-
# If '_verified_elasticsearch' isn't 'True' then we raise an error.
412-
if self._verified_elasticsearch is not True:
413-
_ProductChecker.raise_error(self._verified_elasticsearch)
414-
415402
for attempt in range(self.max_retries + 1):
416403
connection = self.get_connection()
417404

@@ -521,88 +508,6 @@ def _resolve_request_args(self, method, headers, params, body):
521508

522509
return method, headers, params, body, ignore, timeout
523510

524-
def _do_verify_elasticsearch(self, headers, timeout):
525-
"""Verifies that we're connected to an Elasticsearch cluster.
526-
This is done at least once before the first actual API call
527-
and makes a single request to the 'GET /' API endpoint to
528-
check the version along with other details of the response.
529-
530-
If we're unable to verify we're talking to Elasticsearch
531-
but we're also unable to rule it out due to a permission
532-
error we instead emit an 'ElasticsearchWarning'.
533-
"""
534-
# Ensure that there's only one thread within this section
535-
# at a time to not emit unnecessary index API calls.
536-
with self._verify_elasticsearch_lock:
537-
538-
# Product check has already been completed while we were
539-
# waiting our turn, no need to do again.
540-
if self._verified_elasticsearch is not None:
541-
return
542-
543-
headers = {
544-
header.lower(): value for header, value in (headers or {}).items()
545-
}
546-
# We know we definitely want JSON so request it via 'accept'
547-
headers.setdefault("accept", "application/json")
548-
549-
info_headers = {}
550-
info_response = {}
551-
error = None
552-
553-
attempted_conns = []
554-
for conn in chain(self.connection_pool.connections, self.seed_connections):
555-
# Only attempt once per connection max.
556-
if conn in attempted_conns:
557-
continue
558-
attempted_conns.append(conn)
559-
560-
try:
561-
_, info_headers, info_response = conn.perform_request(
562-
"GET", "/", headers=headers, timeout=timeout
563-
)
564-
565-
# Lowercase all the header names for consistency in accessing them.
566-
info_headers = {
567-
header.lower(): value for header, value in info_headers.items()
568-
}
569-
570-
info_response = self.deserializer.loads(
571-
info_response, mimetype="application/json"
572-
)
573-
break
574-
575-
# Previous versions of 7.x Elasticsearch required a specific
576-
# permission so if we receive HTTP 401/403 we should warn
577-
# instead of erroring out.
578-
except (AuthenticationException, AuthorizationException):
579-
warnings.warn(
580-
(
581-
"The client is unable to verify that the server is "
582-
"Elasticsearch due security privileges on the server side"
583-
),
584-
ElasticsearchWarning,
585-
stacklevel=5,
586-
)
587-
self._verified_elasticsearch = True
588-
return
589-
590-
# This connection didn't work, we'll try another.
591-
except (ConnectionError, SerializationError, TransportError) as err:
592-
if error is None:
593-
error = err
594-
595-
# If we received a connection error and weren't successful
596-
# anywhere then we re-raise the more appropriate error.
597-
if error and not info_response:
598-
raise error
599-
600-
# Check the information we got back from the index request.
601-
self._verified_elasticsearch = _ProductChecker.check_product(
602-
info_headers, info_response
603-
)
604-
605-
606511
class _ProductChecker:
607512
"""Class which verifies we're connected to a supported product"""
608513

@@ -624,17 +529,17 @@ def raise_error(cls, state):
624529
)
625530
else: # UNSUPPORTED_PRODUCT
626531
message = (
627-
"The client noticed that the server is not Elasticsearch "
628-
"and we do not support this unknown product"
532+
"The client noticed that the server is not Elasticsearch"
629533
)
630534
raise UnsupportedProductError(message)
631535

632536
@classmethod
633537
def check_product(cls, headers, response):
634538
# type: (dict[str, str], dict[str, str]) -> int
635-
"""Verifies that the server we're talking to is Elasticsearch.
539+
"""Checks whether the server we're talking to is Elasticsearch.
636540
Does this by checking HTTP headers and the deserialized
637-
response to the 'info' API. Returns one of the states above.
541+
response to the 'info' API. Returns true - all servers are
542+
acceptable.
638543
"""
639544
try:
640545
version = response.get("version", {})
@@ -661,21 +566,4 @@ def check_product(cls, headers, response):
661566
bad_build_flavor = True
662567
bad_product_header = True
663568

664-
# 7.0-7.13 and there's a bad 'tagline' or unsupported 'build_flavor'
665-
if (7, 0, 0) <= version_number < (7, 14, 0):
666-
if bad_tagline:
667-
return cls.UNSUPPORTED_PRODUCT
668-
elif bad_build_flavor:
669-
return cls.UNSUPPORTED_DISTRIBUTION
670-
671-
elif (
672-
# No version or version less than 6.x
673-
version_number < (6, 0, 0)
674-
# 6.x and there's a bad 'tagline'
675-
or ((6, 0, 0) <= version_number < (7, 0, 0) and bad_tagline)
676-
# 7.14+ and there's a bad 'X-Elastic-Product' HTTP header
677-
or ((7, 14, 0) <= version_number and bad_product_header)
678-
):
679-
return cls.UNSUPPORTED_PRODUCT
680-
681569
return True

test_elasticsearch/test_async/test_connection.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from mock import patch
2929
from multidict import CIMultiDict
3030

31-
from elasticsearch import AIOHttpConnection, AsyncElasticsearch, __versionstr__
31+
from elasticsearch import AIOHttpConnection, __versionstr__
3232
from elasticsearch.compat import reraise_exceptions
3333
from elasticsearch.exceptions import ConnectionError
3434

@@ -410,9 +410,3 @@ async def test_aiohttp_connection_error(self):
410410
conn = AIOHttpConnection("not.a.host.name")
411411
with pytest.raises(ConnectionError):
412412
await conn.perform_request("GET", "/")
413-
414-
async def test_elasticsearch_connection_error(self):
415-
es = AsyncElasticsearch("http://not.a.host.name")
416-
417-
with pytest.raises(ConnectionError):
418-
await es.search()

0 commit comments

Comments
 (0)