diff --git a/cms/djangoapps/contentstore/courseware_index.py b/cms/djangoapps/contentstore/courseware_index.py index 865ad760bc126594b27d7a3a6c5af4abaa267eee..29a4a9a208739ac4137aa058d84119bcd689e090 100644 --- a/cms/djangoapps/contentstore/courseware_index.py +++ b/cms/djangoapps/contentstore/courseware_index.py @@ -64,7 +64,6 @@ class SearchIndexerBase(object, metaclass=ABCMeta): """ INDEX_NAME = None - DOCUMENT_TYPE = None ENABLE_INDEXING_KEY = None INDEX_EVENT = { @@ -106,12 +105,11 @@ class SearchIndexerBase(object, metaclass=ABCMeta): as we find items we can shorten the set of items to keep """ response = searcher.search( - doc_type=cls.DOCUMENT_TYPE, field_dictionary=cls._get_location_info(structure_key), exclude_dictionary={"id": list(exclude_items)} ) result_ids = [result["data"]["id"] for result in response["results"]] - searcher.remove(cls.DOCUMENT_TYPE, result_ids) + searcher.remove(result_ids) @classmethod def index(cls, modulestore, structure_key, triggered_at=None, reindex_age=REINDEX_AGE): @@ -256,7 +254,7 @@ class SearchIndexerBase(object, metaclass=ABCMeta): # Now index the content for item in structure.get_children(): prepare_item_index(item, groups_usage_info=groups_usage_info) - searcher.index(cls.DOCUMENT_TYPE, items_index) + searcher.index(items_index) cls.remove_deleted_items(searcher, structure_key, indexed_items) except Exception as err: # pylint: disable=broad-except # broad exception so that index operation does not prevent the rest of the application from working @@ -340,8 +338,7 @@ class CoursewareSearchIndexer(SearchIndexerBase): """ Class to perform indexing for courseware search from different modulestores """ - INDEX_NAME = "courseware_index" - DOCUMENT_TYPE = "courseware_content" + INDEX_NAME = "courseware_content" ENABLE_INDEXING_KEY = 'ENABLE_COURSEWARE_INDEX' INDEX_EVENT = { @@ -373,6 +370,24 @@ class CoursewareSearchIndexer(SearchIndexerBase): """ return cls._do_reindex(modulestore, course_key) + @classmethod + def _do_reindex(cls, modulestore, structure_key): + """ + (Re)index course content within the given structure. + + The course_info index is indexed with the courseware_content index. This method + helps to track the fact that course_info reindex has taken place. + """ + indexed_count = super()._do_reindex(modulestore, structure_key) + if indexed_count: + course_about = CourseAboutSearchIndexer + cls._track_index_request( + course_about.INDEX_EVENT['name'], + course_about.INDEX_EVENT['category'], + indexed_count + ) + return indexed_count + @classmethod def fetch_group_usage(cls, modulestore, structure): groups_usage_dict = {} @@ -430,7 +445,6 @@ class LibrarySearchIndexer(SearchIndexerBase): Base class to perform indexing for library search from different modulestores """ INDEX_NAME = "library_index" - DOCUMENT_TYPE = "library_content" ENABLE_INDEXING_KEY = 'ENABLE_LIBRARY_INDEX' INDEX_EVENT = { @@ -531,12 +545,16 @@ class AboutInfo(object): FROM_COURSE_MODE = from_course_mode -class CourseAboutSearchIndexer(object): +class CourseAboutSearchIndexer(CoursewareSearchIndexer): """ Class to perform indexing of about information from course object """ - DISCOVERY_DOCUMENT_TYPE = "course_info" - INDEX_NAME = CoursewareSearchIndexer.INDEX_NAME + INDEX_NAME = "course_info" + + INDEX_EVENT = { + 'name': 'edx.course_info.index.reindexed', + 'category': 'course_info' + } # List of properties to add to the index - each item in the list is an instance of AboutInfo object ABOUT_INFORMATION_TO_INCLUDE = [ @@ -626,7 +644,7 @@ class CourseAboutSearchIndexer(object): # Broad exception handler to protect around and report problems with indexing try: - searcher.index(cls.DISCOVERY_DOCUMENT_TYPE, [course_info]) + searcher.index([course_info]) except: log.exception( u"Course discovery indexing error encountered, course discovery index may be out of date %s", @@ -651,9 +669,6 @@ class CourseAboutSearchIndexer(object): if not searcher: return - response = searcher.search( - doc_type=cls.DISCOVERY_DOCUMENT_TYPE, - field_dictionary=cls._get_location_info(structure_key) - ) + response = searcher.search(field_dictionary=cls._get_location_info(structure_key)) result_ids = [result["data"]["id"] for result in response["results"]] - searcher.remove(cls.DISCOVERY_DOCUMENT_TYPE, result_ids) + searcher.remove(result_ids) diff --git a/cms/djangoapps/contentstore/management/commands/reindex_course.py b/cms/djangoapps/contentstore/management/commands/reindex_course.py index 13ed166470f67b626ce9de4c8fa58ebb0859b7d8..9d5ccf4291dbe8c2ea489d77c6b7ff1c3da0d051 100644 --- a/cms/djangoapps/contentstore/management/commands/reindex_course.py +++ b/cms/djangoapps/contentstore/management/commands/reindex_course.py @@ -12,7 +12,7 @@ from opaque_keys.edx.locator import CourseLocator from search.search_engine_base import SearchEngine from six.moves import map -from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer +from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer, CourseAboutSearchIndexer from xmodule.modulestore.django import modulestore from .prompt import query_yes_no @@ -71,29 +71,23 @@ class Command(BaseCommand): store = modulestore() if index_all_courses_option: - index_name = CoursewareSearchIndexer.INDEX_NAME - doc_type = CoursewareSearchIndexer.DOCUMENT_TYPE + index_names = (CoursewareSearchIndexer.INDEX_NAME, CourseAboutSearchIndexer.INDEX_NAME) if setup_option: - try: - # try getting the ElasticSearch engine - searcher = SearchEngine.get_search_engine(index_name) - except exceptions.ElasticsearchException as exc: - logging.exception(u'Search Engine error - %s', exc) - return - - index_exists = searcher._es.indices.exists(index=index_name) # pylint: disable=protected-access - doc_type_exists = searcher._es.indices.exists_type( # pylint: disable=protected-access - index=index_name, - doc_type=doc_type - ) - - index_mapping = searcher._es.indices.get_mapping( # pylint: disable=protected-access - index=index_name, - doc_type=doc_type - ) if index_exists and doc_type_exists else {} - - if index_exists and index_mapping: - return + for index_name in index_names: + try: + searcher = SearchEngine.get_search_engine(index_name) + except exceptions.ElasticsearchException as exc: + logging.exception(u'Search Engine error - %s', exc) + return + + index_exists = searcher._es.indices.exists(index=index_name) # pylint: disable=protected-access + + index_mapping = searcher._es.indices.get_mapping( # pylint: disable=protected-access + index=index_name, + ) if index_exists else {} + + if index_exists and index_mapping: + return # if reindexing is done during devstack setup step, don't prompt the user if setup_option or query_yes_no(self.CONFIRMATION_PROMPT, default="no"): diff --git a/cms/djangoapps/contentstore/signals/handlers.py b/cms/djangoapps/contentstore/signals/handlers.py index d37a77bc406dae3a2bf9a703be42d0c970113d14..a2f0e8f91d3921a4a44881228982daa10a137b88 100644 --- a/cms/djangoapps/contentstore/signals/handlers.py +++ b/cms/djangoapps/contentstore/signals/handlers.py @@ -10,7 +10,11 @@ from django.core.cache import cache from django.dispatch import receiver from pytz import UTC -from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer, LibrarySearchIndexer +from cms.djangoapps.contentstore.courseware_index import ( + CoursewareSearchIndexer, + CourseAboutSearchIndexer, + LibrarySearchIndexer +) from cms.djangoapps.contentstore.proctoring import register_special_exams from lms.djangoapps.grades.api import task_compute_all_grades_for_course from openedx.core.djangoapps.credit.signals import on_course_publish @@ -62,7 +66,7 @@ def listen_for_course_publish(sender, course_key, **kwargs): # pylint: disable= # Finally call into the course search subsystem # to kick off an indexing action - if CoursewareSearchIndexer.indexing_is_enabled(): + if CoursewareSearchIndexer.indexing_is_enabled() and CourseAboutSearchIndexer.indexing_is_enabled(): # import here, because signal is registered at startup, but items in tasks are not yet able to be loaded from cms.djangoapps.contentstore.tasks import update_search_index diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py index 74ed0f6d32d97903caa41f743dc8f7fb78e3c221..5c54f709528790239149c44cc46f484bfb1096e9 100644 --- a/cms/djangoapps/contentstore/tests/test_courseware_index.py +++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py @@ -137,7 +137,6 @@ class MixedWithOptionsTestCase(MixedSplitTestCase): } INDEX_NAME = None - DOCUMENT_TYPE = None def setup_course_base(self, store): """ base version of setup_course_base is a no-op """ @@ -155,7 +154,7 @@ class MixedWithOptionsTestCase(MixedSplitTestCase): def search(self, field_dictionary=None, query_string=None): """ Performs index search according to passed parameters """ fields = field_dictionary if field_dictionary else self._get_default_search() - return self.searcher.search(query_string=query_string, field_dictionary=fields, doc_type=self.DOCUMENT_TYPE) + return self.searcher.search(query_string=query_string, field_dictionary=fields) def _perform_test_using_store(self, store_type, test_to_perform): """ Helper method to run a test function that uses a specific store """ @@ -248,7 +247,6 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): ) INDEX_NAME = CoursewareSearchIndexer.INDEX_NAME - DOCUMENT_TYPE = CoursewareSearchIndexer.DOCUMENT_TYPE def reindex_course(self, store): """ kick off complete reindex of the course """ @@ -315,7 +313,7 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): """ Test that course will also be delete from search_index after course deletion. """ - self.DOCUMENT_TYPE = 'course_info' # pylint: disable=invalid-name + self.searcher = SearchEngine.get_search_engine(CourseAboutSearchIndexer.INDEX_NAME) response = self.search() self.assertEqual(response["total"], 0) @@ -422,34 +420,43 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): self.assertEqual(indexed_count, 7) def _test_course_about_property_index(self, store): - """ Test that informational properties in the course object end up in the course_info index """ + """ + Test that informational properties in the course object end up in the course_info index. + """ + self.searcher = SearchEngine.get_search_engine(CourseAboutSearchIndexer.INDEX_NAME) display_name = "Help, I need somebody!" self.course.display_name = display_name self.update_item(store, self.course) self.reindex_course(store) response = self.searcher.search( - doc_type=CourseAboutSearchIndexer.DISCOVERY_DOCUMENT_TYPE, field_dictionary={"course": six.text_type(self.course.id)} ) self.assertEqual(response["total"], 1) self.assertEqual(response["results"][0]["data"]["content"]["display_name"], display_name) def _test_course_about_store_index(self, store): - """ Test that informational properties in the about store end up in the course_info index """ + """ + Test that informational properties in the about store end up in + the course_info index. + """ + self.searcher = SearchEngine.get_search_engine(CourseAboutSearchIndexer.INDEX_NAME) short_description = "Not just anybody" CourseDetails.update_about_item( self.course, "short_description", short_description, ModuleStoreEnum.UserID.test, store ) self.reindex_course(store) response = self.searcher.search( - doc_type=CourseAboutSearchIndexer.DISCOVERY_DOCUMENT_TYPE, field_dictionary={"course": six.text_type(self.course.id)} ) self.assertEqual(response["total"], 1) self.assertEqual(response["results"][0]["data"]["content"]["short_description"], short_description) def _test_course_about_mode_index(self, store): - """ Test that informational properties in the course modes store end up in the course_info index """ + """ + Test that informational properties in the course modes store end up in + the course_info index. + """ + self.searcher = SearchEngine.get_search_engine(CourseAboutSearchIndexer.INDEX_NAME) honour_mode = CourseModeFactory( course_id=self.course.id, mode_slug=CourseMode.HONOR, @@ -466,7 +473,6 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): self.reindex_course(store) response = self.searcher.search( - doc_type=CourseAboutSearchIndexer.DISCOVERY_DOCUMENT_TYPE, field_dictionary={"course": six.text_type(self.course.id)} ) self.assertEqual(response["total"], 1) @@ -586,13 +592,15 @@ class TestLargeCourseDeletions(MixedWithOptionsTestCase): WORKS_WITH_STORES = (ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) def _clean_course_id(self): - """ Clean all documents from the index that have a specific course provided """ + """ + Clean all documents from the index that have a specific course provided. + """ if self.course_id: response = self.searcher.search(field_dictionary={"course": self.course_id}) while response["total"] > 0: for item in response["results"]: - self.searcher.remove(CoursewareSearchIndexer.DOCUMENT_TYPE, item["data"]["id"]) + self.searcher.remove(item["data"]["id"]) response = self.searcher.search(field_dictionary={"course": self.course_id}) self.course_id = None @@ -725,10 +733,12 @@ class TestTaskExecution(SharedModuleStoreTestCase): super(TestTaskExecution, cls).tearDownClass() def test_task_indexing_course(self): - """ Making sure that the receiver correctly fires off the task when invoked by signal """ + """ + Making sure that the receiver correctly fires off the task when invoked + by signal. + """ searcher = SearchEngine.get_search_engine(CoursewareSearchIndexer.INDEX_NAME) response = searcher.search( - doc_type=CoursewareSearchIndexer.DOCUMENT_TYPE, field_dictionary={"course": six.text_type(self.course.id)} ) self.assertEqual(response["total"], 0) @@ -737,7 +747,6 @@ class TestTaskExecution(SharedModuleStoreTestCase): # Note that this test will only succeed if celery is working in inline mode response = searcher.search( - doc_type=CoursewareSearchIndexer.DOCUMENT_TYPE, field_dictionary={"course": six.text_type(self.course.id)} ) self.assertEqual(response["total"], 3) @@ -807,7 +816,6 @@ class TestLibrarySearchIndexer(MixedWithOptionsTestCase): ) INDEX_NAME = LibrarySearchIndexer.INDEX_NAME - DOCUMENT_TYPE = LibrarySearchIndexer.DOCUMENT_TYPE def _get_default_search(self): """ Returns field_dictionary for default search """ @@ -1223,22 +1231,24 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase): """ Return content values from args tuple in a mocked calls list. """ - kall = mock_index.call_args - args, kwargs = kall # pylint: disable=unused-variable - return args[1] + call = mock_index.call_args + (indexed_content, ), kwargs = call # pylint: disable=unused-variable + return indexed_content def reindex_course(self, store): """ kick off complete reindex of the course """ return CoursewareSearchIndexer.do_course_reindex(store, self.course.id) def test_content_group_gets_indexed(self): - """ indexing course with content groups added test """ + """ + Indexing course with content groups added test. + """ # Only published modules should be in the index added_to_index = self.reindex_course(self.store) self.assertEqual(added_to_index, 16) response = self.searcher.search(field_dictionary={"course": six.text_type(self.course.id)}) - self.assertEqual(response["total"], 17) + self.assertEqual(response["total"], 16) group_access_content = {'group_access': {666: [1]}} diff --git a/cms/envs/production.py b/cms/envs/production.py index ac11b29662753b15077837493dd3e42dbb0149bd..cd515fcb56d89b3d47f67b3c51cd9d3b9cae0b20 100644 --- a/cms/envs/production.py +++ b/cms/envs/production.py @@ -478,7 +478,8 @@ if FEATURES['ENABLE_COURSEWARE_INDEX'] or FEATURES['ENABLE_LIBRARY_INDEX'] or FE # Use ElasticSearch for the search engine SEARCH_ENGINE = "search.elastic.ElasticSearchEngine" -ELASTIC_SEARCH_CONFIG = ENV_TOKENS.get('ELASTIC_SEARCH_CONFIG', [{}]) +# TODO: Once we have successfully upgraded to ES7, switch this back to ELASTIC_SEARCH_CONFIG. +ELASTIC_SEARCH_CONFIG = ENV_TOKENS.get('ELASTIC_SEARCH_CONFIG_ES7', [{}]) XBLOCK_SETTINGS = ENV_TOKENS.get('XBLOCK_SETTINGS', {}) XBLOCK_SETTINGS.setdefault("VideoBlock", {})["licensing_enabled"] = FEATURES.get("LICENSING", False) diff --git a/lms/djangoapps/course_api/tests/test_views.py b/lms/djangoapps/course_api/tests/test_views.py index 43d019ad808ff05e41ac478d2d93bc2aaaaa0f7b..b38927f4dd8c338fa3d4c40a50ec31740bdbbba8 100644 --- a/lms/djangoapps/course_api/tests/test_views.py +++ b/lms/djangoapps/course_api/tests/test_views.py @@ -286,7 +286,7 @@ class CourseDetailViewTestCase(CourseApiTestViewMixin, SharedModuleStoreTestCase 'enrollment_end': {'type': 'date'} }) @override_settings(SEARCH_ENGINE="search.tests.mock_search_engine.MockSearchEngine") -@override_settings(COURSEWARE_INDEX_NAME=TEST_INDEX_NAME) +@override_settings(COURSEWARE_INFO_INDEX_NAME=TEST_INDEX_NAME) class CourseListSearchViewTest(CourseApiTestViewMixin, ModuleStoreTestCase, SearcherMixin): """ Tests the search functionality of the courses API. diff --git a/lms/djangoapps/teams/search_indexes.py b/lms/djangoapps/teams/search_indexes.py index 32ffcd90927bd58b8734b307871ad04b74ed0d3b..32da8d5ae1261143f54ce58a141c86209ec88831 100644 --- a/lms/djangoapps/teams/search_indexes.py +++ b/lms/djangoapps/teams/search_indexes.py @@ -104,7 +104,7 @@ class CourseTeamIndexer(object): """ search_engine = cls.engine() serialized_course_team = CourseTeamIndexer(course_team).data() - search_engine.index(cls.DOCUMENT_TYPE_NAME, [serialized_course_team]) + search_engine.index([serialized_course_team]) @classmethod @if_search_enabled @@ -112,7 +112,7 @@ class CourseTeamIndexer(object): """ Remove course_team from the index (if feature is enabled). """ - cls.engine().remove(cls.DOCUMENT_TYPE_NAME, [course_team.team_id]) + cls.engine().remove([course_team.team_id]) @classmethod @if_search_enabled diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index eb35d0d107be202d2fa15bebdd062130b727bde2..e273e7ccfba1d8d2267e2c4652a8dd4a8c950e3a 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -73,7 +73,7 @@ from .toggles import are_team_submissions_enabled TEAM_MEMBERSHIPS_PER_PAGE = 5 TOPICS_PER_PAGE = 12 -MAXIMUM_SEARCH_SIZE = 100000 +MAXIMUM_SEARCH_SIZE = 10000 log = logging.getLogger(__name__) diff --git a/lms/envs/production.py b/lms/envs/production.py index c5d7fb1cd40025aa7da1401c56853b404c513b77..578fac7bc2ffa6ada4d8f99d41181dc0beaaac2a 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -724,7 +724,8 @@ if FEATURES.get('ENABLE_COURSEWARE_SEARCH') or \ SEARCH_ENGINE = "search.elastic.ElasticSearchEngine" SEARCH_FILTER_GENERATOR = ENV_TOKENS.get('SEARCH_FILTER_GENERATOR', SEARCH_FILTER_GENERATOR) -ELASTIC_SEARCH_CONFIG = ENV_TOKENS.get('ELASTIC_SEARCH_CONFIG', [{}]) +# TODO: Once we have successfully upgraded to ES7, switch this back to ELASTIC_SEARCH_CONFIG. +ELASTIC_SEARCH_CONFIG = ENV_TOKENS.get('ELASTIC_SEARCH_CONFIG_ES7', [{}]) # Facebook app FACEBOOK_API_VERSION = AUTH_TOKENS.get("FACEBOOK_API_VERSION") diff --git a/requirements/constraints.txt b/requirements/constraints.txt index d5b2ff1cb6e357e3ebc73b04fa5615527569320e..8b2210385f7c5e831c6066e453fcdd5c897e3c60 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -37,9 +37,6 @@ drf-yasg<1.17.1 # for them. edx-enterprise==3.12.0 -# v2 requires the ES7 upgrade work to be complete -edx-search<2.0.0 - # We expect v2.0.0 to introduce large breaking changes in the feature toggle API edx-toggles<2.0.0 diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index cecc6b2a9c0d8b26e4089c8af89b0e9600b61be0..cf2cd5cd2f4fb03f6806c98478ddb96949275f96 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -107,15 +107,15 @@ edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.in edx-proctoring==2.4.8 # via -r requirements/edx/base.in, edx-proctoring-proctortrack edx-rbac==1.3.3 # via edx-enterprise edx-rest-api-client==5.2.1 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring -edx-search==1.4.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in edx-sga==0.13.0 # via -r requirements/edx/base.in edx-submissions==3.2.2 # via -r requirements/edx/base.in, ora2 edx-tincan-py35==0.0.9 # via edx-enterprise edx-toggles==1.2.0 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.in, edx-completion edx-user-state-client==1.2.0 # via -r requirements/edx/base.in +edx-search==2.0.0 # via -r requirements/edx/base.in edx-when==1.3.0 # via -r requirements/edx/base.in, edx-proctoring edxval==1.4.4 # via -r requirements/edx/base.in -elasticsearch==1.9.0 # via edx-search +elasticsearch==7.9.1 # via edx-search enmerkar-underscore==1.0.0 # via -r requirements/edx/base.in enmerkar==0.7.1 # via enmerkar-underscore event-tracking==1.0.0 # via -r requirements/edx/base.in, edx-proctoring, edx-search diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index a6c46815fac320a03197a269b76042ac80de0280..8c32eb4e2af12c8736abcaee9b3fdc0ae2c7877a 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -119,7 +119,7 @@ edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/testing.txt edx-proctoring==2.4.8 # via -r requirements/edx/testing.txt, edx-proctoring-proctortrack edx-rbac==1.3.3 # via -r requirements/edx/testing.txt, edx-enterprise edx-rest-api-client==5.2.1 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring -edx-search==1.4.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/testing.txt +edx-search==2.0.0 # via -r requirements/edx/testing.txt edx-sga==0.13.0 # via -r requirements/edx/testing.txt edx-sphinx-theme==1.5.0 # via -r requirements/edx/development.in edx-submissions==3.2.2 # via -r requirements/edx/testing.txt, ora2 @@ -128,7 +128,7 @@ edx-toggles==1.2.0 # via -c requirements/edx/../constraints.txt, -r requi edx-user-state-client==1.2.0 # via -r requirements/edx/testing.txt edx-when==1.3.0 # via -r requirements/edx/testing.txt, edx-proctoring edxval==1.4.4 # via -r requirements/edx/testing.txt -elasticsearch==1.9.0 # via -r requirements/edx/testing.txt, edx-search +elasticsearch==7.9.1 # via -r requirements/edx/testing.txt, edx-search enmerkar-underscore==1.0.0 # via -r requirements/edx/testing.txt enmerkar==0.7.1 # via -r requirements/edx/testing.txt, enmerkar-underscore event-tracking==1.0.0 # via -r requirements/edx/testing.txt, edx-proctoring, edx-search diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 3035386e1ef6a4116f0339d130d34e0f6c35f9bb..bb4fc5ad5d12d5147102158f53e6d39dc8e14c4c 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -116,7 +116,7 @@ edx-proctoring-proctortrack==1.0.5 # via -r requirements/edx/base.txt edx-proctoring==2.4.8 # via -r requirements/edx/base.txt, edx-proctoring-proctortrack edx-rbac==1.3.3 # via -r requirements/edx/base.txt, edx-enterprise edx-rest-api-client==5.2.1 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring -edx-search==1.4.1 # via -c requirements/edx/../constraints.txt, -r requirements/edx/base.txt +edx-search==2.0.0 # via -r requirements/edx/base.txt edx-sga==0.13.0 # via -r requirements/edx/base.txt edx-submissions==3.2.2 # via -r requirements/edx/base.txt, ora2 edx-tincan-py35==0.0.9 # via -r requirements/edx/base.txt, edx-enterprise @@ -124,7 +124,7 @@ edx-toggles==1.2.0 # via -c requirements/edx/../constraints.txt, -r requi edx-user-state-client==1.2.0 # via -r requirements/edx/base.txt edx-when==1.3.0 # via -r requirements/edx/base.txt, edx-proctoring edxval==1.4.4 # via -r requirements/edx/base.txt -elasticsearch==1.9.0 # via -r requirements/edx/base.txt, edx-search +elasticsearch==7.9.1 # via -r requirements/edx/base.txt, edx-search enmerkar-underscore==1.0.0 # via -r requirements/edx/base.txt enmerkar==0.7.1 # via -r requirements/edx/base.txt, enmerkar-underscore event-tracking==1.0.0 # via -r requirements/edx/base.txt, edx-proctoring, edx-search