Skip to content

Commit ae07e7f

Browse files
Added support for Elasticsearch 8 (#458)
* Updated Pillow version for compatibility with Python 3.8 * Updated alias actions to keyword arguments * Updated elasticsearch-dsl version in requirements * Updated tests * Updated documentation * Updated install requirements in setup.py * Update runtests.py * Update runtests.py * Update runtests.py * Update runtests.py --------- Co-authored-by: Safwan Rahman <[email protected]>
1 parent 7c8e778 commit ae07e7f

File tree

8 files changed

+76
-16
lines changed

8 files changed

+76
-16
lines changed

README.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,17 @@ Features
3737
The library is compatible with all Elasticsearch versions since 5.x
3838
**but you have to use a matching major version:**
3939

40+
- For Elasticsearch 8.0 and later, use the major version 8 (8.x.y) of the library.
41+
4042
- For Elasticsearch 7.0 and later, use the major version 7 (7.x.y) of the library.
4143

4244
- For Elasticsearch 6.0 and later, use the major version 6 (6.x.y) of the library.
4345

4446
.. code-block:: python
4547
48+
# Elasticsearch 8.x
49+
elasticsearch-dsl>=8.0.0,<9.0.0
50+
4651
# Elasticsearch 7.x
4752
elasticsearch-dsl>=7.0.0,<8.0.0
4853

django_elasticsearch_dsl/management/commands/search_index.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def _delete_alias_indices(self, alias):
161161
alias_delete_actions = [
162162
{"remove_index": {"index": index}} for index in alias_indices
163163
]
164-
self.es_conn.indices.update_aliases({"actions": alias_delete_actions})
164+
self.es_conn.indices.update_aliases(actions=alias_delete_actions)
165165
for index in alias_indices:
166166
self.stdout.write("Deleted index '{}'".format(index))
167167

@@ -231,7 +231,7 @@ def _update_alias(self, alias, new_index, alias_exists, options):
231231
{"remove_index": {"index": index}} for index in old_indices
232232
]
233233

234-
self.es_conn.indices.update_aliases({"actions": alias_actions})
234+
self.es_conn.indices.update_aliases(actions=alias_actions)
235235
if delete_existing_index:
236236
self.stdout.write("Deleted index '{}'".format(alias))
237237

@@ -247,7 +247,7 @@ def _update_alias(self, alias, new_index, alias_exists, options):
247247

248248
if alias_delete_actions and not options['use_alias_keep_index']:
249249
self.es_conn.indices.update_aliases(
250-
{"actions": alias_delete_actions}
250+
actions=alias_delete_actions
251251
)
252252
for index in old_indices:
253253
self.stdout.write("Deleted index '{}'".format(index))

docs/source/quickstart.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ For example:
2020
2121
ELASTICSEARCH_DSL={
2222
'default': {
23-
'hosts': 'localhost:9200'
24-
},
23+
'hosts': 'localhost:9200',
24+
'http_auth': ('username', 'password')
25+
}
2526
}
2627
2728
``ELASTICSEARCH_DSL`` is then passed to ``elasticsearch-dsl-py.connections.configure`` (see here_).

example/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
-e ../
55

66
django-autofixture==0.12.1
7-
Pillow==6.2.0
7+
Pillow==6.2.2
88
django==4.1.2

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
django>=3.2
2-
elasticsearch-dsl>=7.0.0,<8.0.0
2+
elasticsearch-dsl>=8.0.0,<9.0.0

runtests.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,27 @@
99
from django.test.utils import get_runner
1010

1111
def get_settings(signal_processor):
12+
elasticsearch_dsl_default_settings = {
13+
'hosts': os.environ.get(
14+
'ELASTICSEARCH_URL',
15+
'https://127.0.0.1:9200'
16+
),
17+
'basic_auth': (
18+
os.environ.get('ELASTICSEARCH_USERNAME'),
19+
os.environ.get('ELASTICSEARCH_PASSWORD')
20+
)
21+
}
22+
23+
elasticsearch_certs_path = os.environ.get(
24+
'ELASTICSEARCH_CERTS_PATH'
25+
)
26+
if elasticsearch_certs_path:
27+
elasticsearch_dsl_default_settings['ca_certs'] = (
28+
elasticsearch_certs_path
29+
)
30+
else:
31+
elasticsearch_dsl_default_settings['verify_certs'] = False
32+
1233
PROCESSOR_CLASSES = {
1334
'realtime': 'django_elasticsearch_dsl.signals.RealTimeSignalProcessor',
1435
'celery': 'django_elasticsearch_dsl.signals.CelerySignalProcessor',
@@ -33,10 +54,7 @@ def get_settings(signal_processor):
3354
SITE_ID=1,
3455
MIDDLEWARE_CLASSES=(),
3556
ELASTICSEARCH_DSL={
36-
'default': {
37-
'hosts': os.environ.get('ELASTICSEARCH_URL',
38-
'127.0.0.1:9200')
39-
},
57+
'default': elasticsearch_dsl_default_settings
4058
},
4159
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
4260
CELERY_BROKER_URL='memory://localhost/',
@@ -81,13 +99,42 @@ def make_parser():
8199
choices=('realtime', 'celery'),
82100
help='Defines which signal backend to choose'
83101
)
102+
parser.add_argument(
103+
'--elasticsearch-username',
104+
nargs='?',
105+
help="Username for Elasticsearch user"
106+
)
107+
parser.add_argument(
108+
'--elasticsearch-password',
109+
nargs='?',
110+
help="Password for Elasticsearch user"
111+
)
112+
parser.add_argument(
113+
'--elasticsearch-certs-path',
114+
nargs='?',
115+
help="Path to CA certificates for Elasticsearch"
116+
)
84117
return parser
85118

86119

87120
def run_tests(*test_args):
88121
args, test_args = make_parser().parse_known_args(test_args)
89122
if args.elasticsearch:
90-
os.environ.setdefault('ELASTICSEARCH_URL', args.elasticsearch)
123+
os.environ.setdefault('ELASTICSEARCH_URL', "https://127.0.0.1:9200")
124+
125+
username = args.elasticsearch_username or "elastic"
126+
password = args.elasticsearch_password or "changeme"
127+
os.environ.setdefault(
128+
'ELASTICSEARCH_USERNAME', username
129+
)
130+
os.environ.setdefault(
131+
'ELASTICSEARCH_PASSWORD', password
132+
)
133+
134+
if args.elasticsearch_certs_path:
135+
os.environ.setdefault(
136+
'ELASTICSEARCH_CERTS_PATH', args.elasticsearch_certs_path
137+
)
91138

92139
if not test_args:
93140
test_args = ['tests']

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
],
4343
include_package_data=True,
4444
install_requires=[
45-
'elasticsearch-dsl>=7.2.0,<8.0.0',
45+
'elasticsearch-dsl>=8.9.0,<9.0.0',
4646
'six',
4747
],
4848
license="Apache Software License 2.0",

tests/test_documents.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ def generate_id(cls, article):
508508

509509
# Get the data from the elasticsearch low level API because
510510
# The generator get executed there.
511-
data = json.loads(mock_bulk.call_args[1]['body'].split("\n")[0])
512-
assert data["index"]["_id"] == article.slug
511+
data = json.loads(mock_bulk.call_args[1]['operations'][1])
512+
assert data['slug'] == article.slug
513513

514514
@patch('elasticsearch_dsl.connections.Elasticsearch.bulk')
515515
def test_should_index_object_is_called(self, mock_bulk):
@@ -549,6 +549,13 @@ def should_index_object(self, obj):
549549

550550
d = ArticleDocument()
551551
d.update([article1, article2])
552+
operations = mock_bulk.call_args[1]['operations']
553+
slugs = [
554+
json.loads(operation)['slug'] for operation in operations
555+
if 'slug' in json.loads(operation)
556+
]
557+
self.assertTrue(article1.slug in slugs)
558+
self.assertTrue(article2.slug not in slugs)
552559
data_body = mock_bulk.call_args[1]['body']
553560
self.assertTrue(article1.slug in data_body)
554561
self.assertTrue(article2.slug not in data_body)
@@ -558,4 +565,4 @@ class RealTimeDocTypeTestCase(BaseDocTypeTestCase, TestCase):
558565

559566

560567
class CeleryDocTypeTestCase(BaseDocTypeTestCase, TestCase):
561-
TARGET_PROCESSOR = 'django_elasticsearch_dsl.signals.CelerySignalProcessor'
568+
TARGET_PROCESSOR = 'django_elasticsearch_dsl.signals.CelerySignalProcessor'

0 commit comments

Comments
 (0)