diff --git a/Changelog.rst b/Changelog.rst index 88a90334a..37d407c9b 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -4,6 +4,7 @@ Changelog ========= 7.1.0 (dev) ----------- + * Add connection parameter for Elastic Cloud cloud_id. 7.0.1 (2019-05019) ----------- diff --git a/README b/README index 0b22fb447..ecebbaba7 100644 --- a/README +++ b/README @@ -80,15 +80,22 @@ Simple use-case:: # create an index in elasticsearch, ignore status code 400 (index already exists) >>> es.indices.create(index='my-index', ignore=400) - {u'acknowledged': True} + {'acknowledged': True, 'shards_acknowledged': True, 'index': 'my-index'} # datetimes will be serialized >>> es.index(index="my-index", id=42, body={"any": "data", "timestamp": datetime.now()}) - {u'_id': u'42', u'_index': u'my-index', u'_type': u'test-type', u'_version': 1, u'ok': True} + {'_index': 'my-index', + '_type': '_doc', + '_id': '42', + '_version': 1, + 'result': 'created', + '_shards': {'total': 2, 'successful': 1, 'failed': 0}, + '_seq_no': 0, + '_primary_term': 1} # but not deserialized >>> es.get(index="my-index", id=42)['_source'] - {u'any': u'data', u'timestamp': u'2013-05-12T19:45:31.804229'} + {'any': 'data', 'timestamp': '2019-05-17T17:28:10.329598'} `Full documentation`_. @@ -97,7 +104,7 @@ Simple use-case:: Elastic Cloud (and SSL) use-case:: >>> from elasticsearch import Elasticsearch - >>> es = Elasticsearch("https://elasticsearch.url:port", http_auth=('elastic','yourpassword')) + >>> es = Elasticsearch(cloud_id="", http_auth=('elastic','yourpassword')) >>> es.info() Using SSL Context with a self-signed cert use-case:: diff --git a/elasticsearch/connection/http_requests.py b/elasticsearch/connection/http_requests.py index 3a0a3c00f..e2a7a218e 100644 --- a/elasticsearch/connection/http_requests.py +++ b/elasticsearch/connection/http_requests.py @@ -1,5 +1,6 @@ import time import warnings +from base64 import decodestring try: import requests @@ -34,6 +35,8 @@ class RequestsHttpConnection(Connection): :arg client_key: path to the file containing the private key if using separate cert and key files (client_cert will contain only the cert) :arg headers: any custom http headers to be add to requests + :arg cloud_id: The Cloud ID from ElasticCloud. Convient way to connect to cloud instances. + Other host connection params will be ignored. """ def __init__( @@ -48,12 +51,21 @@ def __init__( client_cert=None, client_key=None, headers=None, + cloud_id=None, **kwargs ): if not REQUESTS_AVAILABLE: raise ImproperlyConfigured( "Please install requests to use RequestsHttpConnection." ) + if cloud_id: + cluster_name, cloud_id = cloud_id.split(":") + url, es_uuid, kibana_uuid = ( + decodestring(cloud_id.encode("utf-8")).decode("utf-8").split("$") + ) + host = "%s.%s" % (es_uuid, url) + port = 9243 + use_ssl = True super(RequestsHttpConnection, self).__init__( host=host, port=port, use_ssl=use_ssl, **kwargs diff --git a/elasticsearch/connection/http_urllib3.py b/elasticsearch/connection/http_urllib3.py index d573b0b9a..d698f7490 100644 --- a/elasticsearch/connection/http_urllib3.py +++ b/elasticsearch/connection/http_urllib3.py @@ -5,6 +5,7 @@ from urllib3.util.retry import Retry import warnings import gzip +from base64 import decodestring # sentinal value for `verify_certs`. # This is used to detect if a user is passing in a value for `verify_certs` @@ -72,6 +73,8 @@ class Urllib3HttpConnection(Connection): information. :arg headers: any custom http headers to be add to requests :arg http_compress: Use gzip compression + :arg cloud_id: The Cloud ID from ElasticCloud. Convient way to connect to cloud instances. + Other host connection params will be ignored. """ def __init__( @@ -92,9 +95,18 @@ def __init__( headers=None, ssl_context=None, http_compress=False, + cloud_id=None, **kwargs ): + if cloud_id: + cluster_name, cloud_id = cloud_id.split(":") + url, es_uuid, kibana_uuid = ( + decodestring(cloud_id.encode("utf-8")).decode("utf-8").split("$") + ) + host = "%s.%s" % (es_uuid, url) + port = "9243" + use_ssl = True super(Urllib3HttpConnection, self).__init__( host=host, port=port, use_ssl=use_ssl, **kwargs ) diff --git a/test_elasticsearch/test_connection.py b/test_elasticsearch/test_connection.py index 478897c2c..e7e9de72e 100644 --- a/test_elasticsearch/test_connection.py +++ b/test_elasticsearch/test_connection.py @@ -34,6 +34,15 @@ def test_ssl_context(self): self.assertIsInstance(con.pool.conn_kw["ssl_context"], ssl.SSLContext) self.assertTrue(con.use_ssl) + def test_http_cloud_id(self): + con = Urllib3HttpConnection( + cloud_id="foobar:ZXhhbXBsZS5jbG91ZC5jb20kMGZkNTBmNjIzMjBlZDY1MzlmNmNiNDhlMWI2OCRhYzUzOTVhODgz\nNDU2NmM5ZjE1Y2Q4ZTQ5MGE=\n" + ) + self.assertTrue(con.use_ssl) + self.assertEquals( + con.host, "https://0fd50f62320ed6539f6cb48e1b68.example.cloud.com:9243" + ) + def test_http_compression(self): con = Urllib3HttpConnection(http_compress=True) self.assertTrue(con.http_compress) @@ -151,6 +160,15 @@ def test_timeout_set(self): con = RequestsHttpConnection(timeout=42) self.assertEquals(42, con.timeout) + def test_http_cloud_id(self): + con = RequestsHttpConnection( + cloud_id="foobar:ZXhhbXBsZS5jbG91ZC5jb20kMGZkNTBmNjIzMjBlZDY1MzlmNmNiNDhlMWI2OCRhYzUzOTVhODgz\nNDU2NmM5ZjE1Y2Q4ZTQ5MGE=\n" + ) + self.assertTrue(con.use_ssl) + self.assertEquals( + con.host, "https://0fd50f62320ed6539f6cb48e1b68.example.cloud.com:9243" + ) + def test_uses_https_if_verify_certs_is_off(self): with warnings.catch_warnings(record=True) as w: con = self._get_mock_connection(