SERVER-85198 create a MongoTFixture for resmoke and enable launching mongot in a single node repl set

GitOrigin-RevId: c5f03fef09aeb16db7e27d07ddbb55005d6e83c4
This commit is contained in:
madelinezec 2024-02-23 16:34:11 +00:00 committed by MongoDB Bot
parent 253e3a8fb1
commit bd965e368a
14 changed files with 386 additions and 29 deletions

View File

@ -0,0 +1,41 @@
config_variables:
- &keyFile jstests/with_mongot/keyfile_for_testing
- &keyFileData Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly
- &authOptions
authenticationDatabase: local
authenticationMechanism: SCRAM-SHA-256
password: *keyFileData
username: __system
test_kind: js_test
description: |
This suite spins up a single node replica set (eg a single, primary node) with a mongot for
running search integrations tests locally and on evergreen. Given that it is a single repl
node, the suite's read preference is the primary.
selector:
roots:
- jstests/with_mongot/e2e/*.js
executor:
config:
shell_options:
global_vars:
TestData: &TestData
auth: true
authMechanism: SCRAM-SHA-256
keyFile: *keyFile
keyFileData: *keyFileData
roleGraphInvalidationIsFatal: true
eval: jsTest.authenticate(db.getMongo())
<<: *authOptions
fixture:
class: ReplicaSetFixture
auth_options: *authOptions
launch_mongot: true
num_nodes: 1
mongod_options:
keyFile: *keyFile
set_parameters:
enableTestCommands: 1

View File

@ -29,6 +29,9 @@ DEFAULT_DBTEST_EXECUTABLE = os.path.join(os.curdir, "dbtest")
DEFAULT_MONGO_EXECUTABLE = "mongo"
DEFAULT_MONGOD_EXECUTABLE = "mongod"
DEFAULT_MONGOS_EXECUTABLE = "mongos"
# TODO SERVER-85977 potentially replace with "mongot" if possible to add a symlink from raw path
# below as part of setup-mongot-repro.
DEFAULT_MONGOT_EXECUTABLE = "mongot-localdev/mongot"
DEFAULT_BENCHMARK_REPETITIONS = 3
DEFAULT_BENCHMARK_MIN_TIME = datetime.timedelta(seconds=5)
@ -81,6 +84,8 @@ DEFAULTS = {
"mongod_set_parameters": [],
"mongos_executable": None,
"mongos_set_parameters": [],
"mongot-localdev/mongot_executable": None,
"mongot_set_parameters": [],
"mongocryptd_set_parameters": [],
"mrlog": None,
"no_journal": False,
@ -460,6 +465,12 @@ MONGOS_EXECUTABLE = None
# The --setParameter options passed to mongos.
MONGOS_SET_PARAMETERS = []
# The path to the mongot executable used by resmoke.py.
MONGOT_EXECUTABLE = None
# The --setParameter options passed to mongot.
MONGOT_SET_PARAMETERS = []
# The --setParameter options passed to mongocryptd.
MONGOCRYPTD_SET_PARAMETERS = []

View File

@ -365,7 +365,7 @@ or explicitly pass --installDir to the run subcommand of buildscripts/resmoke.py
# Windows PATH variable requires absolute paths.
_config.INSTALL_DIR = os.path.abspath(_expand_user(os.path.normpath(_config.INSTALL_DIR)))
for binary in ["mongo", "mongod", "mongos", "dbtest"]:
for binary in ["mongo", "mongod", "mongos", "mongot-localdev/mongot", "dbtest"]:
keyname = binary + "_executable"
if config.get(keyname, None) is None:
config[keyname] = os.path.join(_config.INSTALL_DIR, binary)
@ -414,6 +414,10 @@ or explicitly pass --installDir to the run subcommand of buildscripts/resmoke.py
_config.MONGOCRYPTD_SET_PARAMETERS = _merge_set_params(config.pop("mongocryptd_set_parameters"))
_config.MONGOT_EXECUTABLE = _expand_user(config.pop("mongot-localdev/mongot_executable"))
mongot_set_parameters = config.pop("mongot_set_parameters")
_config.MONGOT_SET_PARAMETERS = _merge_set_params(mongot_set_parameters)
_config.MRLOG = config.pop("mrlog")
_config.NO_JOURNAL = config.pop("no_journal")
_config.NUM_CLIENTS_PER_FIXTURE = config.pop("num_clients_per_fixture")

View File

@ -208,6 +208,17 @@ def mongos_program(logger, job_num, executable=None, process_kwargs=None, mongos
return make_process(logger, args, **process_kwargs), final_mongos_options
def mongot_program(logger, job_num, executable=None, process_kwargs=None, mongot_options=None):
"""Return a Process instance that starts a mongot."""
args = [executable]
mongot_options = mongot_options.copy()
final_mongot_options = mongot_options.copy()
# Apply the rest of the command line arguments.
_apply_kwargs(args, mongot_options)
process_kwargs = make_historic(utils.default_if_none(process_kwargs, {}))
return make_process(logger, args, **process_kwargs), final_mongot_options
def mongo_shell_program(logger, executable=None, connection_string=None, filename=None,
test_filename=None, process_kwargs=None, **kwargs):
"""Return a Process instance that starts a mongo shell.

View File

@ -177,6 +177,8 @@ class ReplSetBuilder(FixtureBuilder):
:param existing_nodes: the list of mongod fixtures
:return: configured replica set fixture
"""
launch_mongot = bool("launch_mongot" in kwargs)
self._mutate_kwargs(kwargs)
mixed_bin_versions, old_bin_version = _extract_multiversion_options(kwargs)
self._validate_multiversion_options(kwargs, mixed_bin_versions)
@ -199,15 +201,16 @@ class ReplSetBuilder(FixtureBuilder):
for node_index in range(replset.num_nodes):
node = self._new_mongod(replset, node_index, mongod_executables, mongod_class,
mongod_binary_versions[node_index], is_multiversion)
mongod_binary_versions[node_index], is_multiversion,
launch_mongot)
replset.install_mongod(node)
if replset.start_initial_sync_node:
if not replset.initial_sync_node:
replset.initial_sync_node_idx = replset.num_nodes
replset.initial_sync_node = self._new_mongod(replset, replset.initial_sync_node_idx,
mongod_executables, mongod_class,
BinVersionEnum.NEW, is_multiversion)
replset.initial_sync_node = self._new_mongod(
replset, replset.initial_sync_node_idx, mongod_executables, mongod_class,
BinVersionEnum.NEW, is_multiversion, launch_mongot)
return replset
@ -302,7 +305,7 @@ class ReplSetBuilder(FixtureBuilder):
@staticmethod
def _new_mongod(replset: ReplicaSetFixture, replset_node_index: int,
executables: Dict[str, str], _class: str, cur_version: str,
is_multiversion: bool) -> FixtureContainer:
is_multiversion: bool, launch_mongot: bool) -> FixtureContainer:
"""Make a fixture container with configured mongod fixture(s) in it.
In non-multiversion mode only a new mongod fixture will be in the fixture container.
@ -334,11 +337,11 @@ class ReplSetBuilder(FixtureBuilder):
new_fixture_port = old_fixture.port
new_fixture_mongod_options = replset.get_options_for_mongod(replset_node_index)
new_fixture = make_fixture(_class, mongod_logger, replset.job_num,
mongod_executable=executables[BinVersionEnum.NEW],
mongod_options=new_fixture_mongod_options,
preserve_dbpath=replset.preserve_dbpath, port=new_fixture_port)
preserve_dbpath=replset.preserve_dbpath, port=new_fixture_port,
launch_mongot=launch_mongot)
return FixtureContainer(new_fixture, old_fixture, cur_version)

View File

@ -63,6 +63,12 @@ class FixtureLib:
return core.programs.mongos_program(logger, job_num, executable, process_kwargs,
mongos_options)
def mongot_program(self, logger, job_num, executable=None, process_kwargs=None,
mongot_options=None):
"""Return a Process instance that starts a mongot with arguments constructed from 'kwargs'."""
return core.programs.mongot_program(logger, job_num, executable, process_kwargs,
mongot_options)
def generic_program(self, logger, args, process_kwargs=None, **kwargs):
"""Return a Process instance that starts an arbitrary executable.
@ -153,6 +159,8 @@ class _FixtureConfig(object):
self.DEFAULT_MONGOS_EXECUTABLE = config.DEFAULT_MONGOS_EXECUTABLE
self.MONGOS_EXECUTABLE = config.MONGOS_EXECUTABLE
self.MONGOS_SET_PARAMETERS = config.MONGOS_SET_PARAMETERS
self.DEFAULT_MONGOT_EXECUTABLE = config.DEFAULT_MONGOT_EXECUTABLE
self.MONGOT_EXECUTABLE = config.MONGOT_EXECUTABLE
self.DBPATH_PREFIX = config.DBPATH_PREFIX
self.DEFAULT_DBPATH_PREFIX = config.DEFAULT_DBPATH_PREFIX
self.DOCKER_COMPOSE_BUILD_IMAGES = config.DOCKER_COMPOSE_BUILD_IMAGES

View File

@ -243,27 +243,27 @@ class DockerComposeException(Exception):
class _DockerComposeInterface:
"""
Implement the `_all_mongo_d_s_instances` method which returns all `mongo{d,s}` instances.
Implement the `_all_mongo_d_s_t_instances` method which returns all `mongo{d,s,t}` instances.
Fixtures that use this interface can programmatically generate `docker-compose.yml` configurations
by leveraging the `all_processes` method to access the startup args.
"""
def _all_mongo_d_s(self) -> List[Fixture]:
def _all_mongo_d_s_t(self) -> List[Fixture]:
"""
Return a list of all mongo{d,s} `Fixture` instances in this fixture.
Return a list of all mongo{d,s,t} `Fixture` instances in this fixture.
:return: A list of `mongo{d,s}` `Fixture` instances.
:return: A list of `mongo{d,s,t}` `Fixture` instances.
"""
raise NotImplementedError(
"_all_mongo_d_s_instances must be implemented by Fixture subclasses that support `docker-compose.yml` generation."
"_all_mongo_d_s_t_instances must be implemented by Fixture subclasses that support `docker-compose.yml` generation."
)
def all_processes(self) -> List['Process']:
"""
Return a list of all `mongo{d,s}` `Process` instances in the fixture.
Return a list of all `mongo{d,s,t}` `Process` instances in the fixture.
:return: A list of mongo{d,s} processes for the current fixture.
:return: A list of mongo{d,s,t} processes for the current fixture.
"""
if not self.config.DOCKER_COMPOSE_BUILD_IMAGES:
raise DockerComposeException(
@ -273,7 +273,7 @@ class _DockerComposeInterface:
# If `mongo_d_s.NOOP_MONGO_D_S_PROCESSES=True`, `mongo_d_s.setup()` will setup a dummy process
# to extract args from instead of a real `mongo{d,s}`.
for mongo_d_s in self._all_mongo_d_s():
for mongo_d_s in self._all_mongo_d_s_t():
if mongo_d_s.__class__.__name__ == "MongoDFixture":
mongo_d_s.setup()
processes += [mongo_d_s.mongod]

View File

@ -0,0 +1,197 @@
"""Mongot fixture for executing JSTests against.
Mongot is a MongoDB-specific process written as a wrapper around Lucene. Using Lucene, mongot indexes MongoDB databases to provide our customers with full text search capabilities.
Customers have the option of running mongot on Atlas or locally using a special "local-dev" binary of mongot. The local-dev binary allows mongot and mongod to speak directly on the localhost, rather than via proprietary network proxies configured by the Atlas Data Plane.
A resmoke suite's yml definition can enable launching mongot(s) enabled via the launch_mongot option on the ReplicaSetFixture and providing a keyfile. If enabled, the ReplicaSetFixture launches a local-dev version of mongot per mongod node. The mongot replicates directly from the co-located
mongod via a $changeStream.
"""
import os
import os.path
import time
import shutil
import uuid
import yaml
import pymongo
import pymongo.errors
from buildscripts.resmokelib.testing.fixtures import interface
class MongoTFixture(interface.Fixture, interface._DockerComposeInterface):
"""Fixture which provides JSTests with a mongot to run alongside a mongod."""
def __init__(self, logger, job_num, fixturelib, dbpath_prefix=None, mongot_options=None):
interface.Fixture.__init__(self, logger, job_num, fixturelib)
self.mongot_options = self.fixturelib.make_historic(
self.fixturelib.default_if_none(mongot_options, {}))
# Default to command line options if the YAML configuration is not passed in.
self.mongot_executable = self.fixturelib.default_if_none(self.config.MONGOT_EXECUTABLE)
self.port = self.mongot_options["port"]
self.mongot = None
def setup(self):
"""Set up and launch the mongot."""
launcher = MongotLauncher(self.fixturelib)
# Second return val is the port, which we ignore because we explicitly generated the port number in MongoDFixture initialization and save to MongotFixture in above initialization function.
mongot, _ = launcher.launch_mongot_program(self.logger, self.job_num,
executable=self.mongot_executable,
mongot_options=self.mongot_options)
try:
msg = f"Starting mongot on port { self.port } ...\n{ mongot.as_command() }"
self.logger.info(msg)
mongot.start()
msg = f"mongot started on port { self.port } with pid { mongot.pid }"
self.logger.info(msg)
except Exception as err:
msg = "Failed to start mongot on port {:d}: {}".format(self.port, err)
self.logger.exception(msg)
raise self.fixturelib.ServerFailure(msg)
self.mongot = mongot
def _all_mongo_d_s_t(self):
"""Return the `mongot` `Process` instance."""
return [self]
def pids(self):
""":return: pids owned by this fixture if any."""
out = [x.pid for x in [self.mongot] if x is not None]
if not out:
self.logger.debug('Mongot not running when gathering mongot fixture pid.')
return out
def _do_teardown(self, mode=None):
if self.config.NOOP_MONGO_D_S_PROCESSES:
self.logger.info(
"This is running against an External System Under Test setup with `docker-compose.yml` -- skipping teardown."
)
return
if self.mongot is None:
self.logger.warning("The mongot fixture has not been set up yet.")
return # Still a success even if nothing is running.
if mode == interface.TeardownMode.ABORT:
self.logger.info(
"Attempting to send SIGABRT from resmoke to mongot on port %d with pid %d...",
self.port, self.mongot.pid)
else:
self.logger.info("Stopping mongot on port %d with pid %d...", self.port,
self.mongot.pid)
if not self.is_running():
exit_code = self.mongot.poll()
msg = ("mongot on port {:d} was expected to be running, but wasn't. "
"Process exited with code {:d}.").format(self.port, exit_code)
self.logger.warning(msg)
raise self.fixturelib.ServerFailure(msg)
self.mongot.stop(mode)
exit_code = self.mongot.wait()
# Java applications return exit code of 143 when they shut down upon receiving and obeying a SIGTERM signal, which is the desired/default mode.
if exit_code == 143 or (mode is not None and exit_code == -(mode.value)):
self.logger.info("Successfully stopped the mongot on port {:d}.".format(self.port))
else:
self.logger.warning("Stopped the mongot on port {:d}. "
"Process exited with code {:d}.".format(self.port, exit_code))
raise self.fixturelib.ServerFailure(
"mongot on port {:d} with pid {:d} exited with code {:d}".format(
self.port, self.mongot.pid, exit_code))
def is_running(self):
"""Return true if the mongot is still operating."""
return self.mongot is not None and self.mongot.poll() is None
def get_dbpath_prefix(self):
"""Return the _dbpath, as this is the root of the data directory."""
return self._dbpath
def get_node_info(self):
"""Return a list of NodeInfo objects."""
if self.mongot is None:
self.logger.warning("The mongot fixture has not been set up yet.")
return []
info = interface.NodeInfo(full_name=self.logger.full_name, name=self.logger.name,
port=self.port, pid=self.mongot.pid, router_port=self.router_port)
return [info]
def get_internal_connection_string(self):
"""Return the internal connection string."""
return f"localhost:{self.port}"
def get_driver_connection_url(self):
"""Return the driver connection URL."""
return "mongodb://" + self.get_internal_connection_string() + "/?directConnection=true"
def await_ready(self):
"""Block until the fixture can be used for testing."""
deadline = time.time() + MongoTFixture.AWAIT_READY_TIMEOUT_SECS
# Wait until the mongot is accepting connections. The retry logic is necessary to support
# versions of PyMongo <3.0 that immediately raise a ConnectionFailure if a connection cannot
# be established.
while True:
# Check whether the mongot exited for some reason.
exit_code = self.mongot.poll()
if exit_code is not None:
raise self.fixturelib.ServerFailure(
"Could not connect to mongot on port {}, process ended"
" unexpectedly with code {}.".format(self.port, exit_code))
try:
# By connecting to the host and port that mongot is listening from,
# we ensure mongot specifically is receiving the ping command.
client = pymongo.MongoClient(self.get_driver_connection_url())
client.admin.command("hello")
break
except pymongo.errors.ConnectionFailure:
remaining = deadline - time.time()
if remaining <= 0.0:
raise self.fixturelib.ServerFailure(
"Failed to connect to mongot on port {} after {} seconds".format(
self.port, MongoTFixture.AWAIT_READY_TIMEOUT_SECS))
self.logger.info("Waiting to connect to mongot on port %d.", self.port)
time.sleep(0.1) # Wait a little bit before trying again.
self.logger.info("Successfully contacted the mongot on port %d.", self.port)
class MongotLauncher(object):
"""Class with utilities for launching a mongot."""
def __init__(self, fixturelib):
"""Initialize MongotLauncher."""
self.fixturelib = fixturelib
self.config = fixturelib.get_config()
def launch_mongot_program(self, logger, job_num, executable=None, process_kwargs=None,
mongot_options=None):
"""
Return a Process instance that starts a mongot with arguments constructed from 'mongot_options'.
@param logger - The logger to pass into the process.
@param executable - The mongot executable to run.
@param process_kwargs - A dict of key-value pairs to pass to the process.
@param mongot_options - A HistoryDict describing the various options to pass to the mongot.
Currently, this will launch a mongot with --port, --mongodHostAndPort, and --keyFile commandline
options. To support launching mongot with more startup options, those new options would need to
be added to mongot_options in MongoTFixture initialization or, if mongod needs to share/know the
mongot startup option (like in the case of keyFile), in MongoDFixture::setup_mongot().
"""
executable = self.fixturelib.default_if_none(executable,
self.config.DEFAULT_MONGOD_EXECUTABLE)
mongot_options = self.fixturelib.default_if_none(mongot_options, {}).copy()
return self.fixturelib.mongot_program(logger, job_num, executable, process_kwargs,
mongot_options)

View File

@ -49,7 +49,7 @@ class ReplicaSetFixture(interface.ReplFixture, interface._DockerComposeInterface
default_read_concern=None, default_write_concern=None, shard_logging_prefix=None,
replicaset_logging_prefix=None, replset_name=None, config_shard=None,
use_auto_bootstrap_procedure=None, initial_sync_uninitialized_fcv=False,
hide_initial_sync_node_from_conn_string=False):
hide_initial_sync_node_from_conn_string=False, launch_mongot=False):
"""Initialize ReplicaSetFixture."""
interface.ReplFixture.__init__(self, logger, job_num, fixturelib,
@ -79,7 +79,8 @@ class ReplicaSetFixture(interface.ReplFixture, interface._DockerComposeInterface
# Used by the enhanced multiversion system to signify multiversion mode.
# None implies no multiversion run.
self.fcv = None
# Used by suites that run search integration tests.
self.launch_mongot = launch_mongot
# Use the values given from the command line if they exist for linear_chain and num_nodes.
linear_chain_option = self.fixturelib.default_if_none(self.config.LINEAR_CHAIN,
linear_chain)
@ -263,9 +264,15 @@ class ReplicaSetFixture(interface.ReplFixture, interface._DockerComposeInterface
self._await_secondaries()
self._await_newly_added_removals()
def _all_mongo_d_s(self):
"""Return a list of all `mongo{d,s}` `Process` instances in this fixture."""
return sum([node._all_mongo_d_s() for node in self.nodes], [])
if self.launch_mongot:
# To model Atlas Search's coupled architecture, resmoke deploys a mongot for each
# mongod node in a replica set.
for node in self.nodes:
node.setup_mongot()
def _all_mongo_d_s_t(self):
"""Return a list of all `mongo{d,s,t}` `Process` instances in this fixture."""
return sum([node._all_mongo_d_s_t() for node in self.nodes], [])
def pids(self):
""":return: all pids owned by this fixture if any."""

View File

@ -140,17 +140,17 @@ class ShardedClusterFixture(interface.Fixture, interface._DockerComposeInterface
for shard in self.shards:
shard.setup()
def _all_mongo_d_s(self):
"""Return a list of all `mongo{d,s}` `Process` instances in this fixture."""
def _all_mongo_d_s_t(self):
"""Return a list of all `mongo{d,s,t}` `Process` instances in this fixture."""
# When config_shard is None, we have an additional replset for the configsvr.
all_nodes = [self.configsvr] if self.config_shard is None else []
all_nodes += self.mongos
all_nodes += self.shards
return sum([node._all_mongo_d_s() for node in all_nodes], [])
return sum([node._all_mongo_d_s_t() for node in all_nodes], [])
def get_shardsvrs(self):
"""Return a list of the `MongodFixture`s for all of the shardsvrs in the cluster."""
return sum([shard._all_mongo_d_s() for shard in self.shards], [])
return sum([shard._all_mongo_d_s_t() for shard in self.shards], [])
def refresh_logical_session_cache(self, target):
"""Refresh logical session cache with no timeout."""
@ -673,7 +673,7 @@ class _MongoSFixture(interface.Fixture, interface._DockerComposeInterface):
self.mongos = mongos
def _all_mongo_d_s(self):
def _all_mongo_d_s_t(self):
"""Return the standalone `mongos` `Process` instance."""
return [self]

View File

@ -10,15 +10,18 @@ import yaml
import pymongo
import pymongo.errors
from buildscripts.resmokelib.testing.fixtures import interface
from buildscripts.resmokelib.testing.fixtures.fixturelib import FixtureLib
from buildscripts.resmokelib.testing.fixtures.interface import _FIXTURES
from buildscripts.resmokelib.testing.fixtures.mongot import MongoTFixture
class MongoDFixture(interface.Fixture, interface._DockerComposeInterface):
"""Fixture which provides JSTests with a standalone mongod to run against."""
def __init__(self, logger, job_num, fixturelib, mongod_executable=None, mongod_options=None,
add_feature_flags=False, dbpath_prefix=None, preserve_dbpath=False, port=None):
add_feature_flags=False, dbpath_prefix=None, preserve_dbpath=False, port=None,
launch_mongot=False):
"""Initialize MongoDFixture with different options for the mongod process."""
interface.Fixture.__init__(self, logger, job_num, fixturelib, dbpath_prefix=dbpath_prefix)
self.mongod_options = self.fixturelib.make_historic(
@ -56,6 +59,19 @@ class MongoDFixture(interface.Fixture, interface._DockerComposeInterface):
self.port = port or fixturelib.get_next_port(job_num)
self.mongod_options["port"] = self.port
if launch_mongot:
self.launch_mongot = True
self.mongot_port = fixturelib.get_next_port(job_num)
self.mongod_options["mongotHost"] = "localhost:" + str(self.mongot_port)
# In future architectures, this could change
self.mongod_options["searchIndexManagementHostAndPort"] = self.mongod_options[
"mongotHost"]
else:
self.launch_mongot = False
# If a suite enables launching mongot, the MongoTFixture will be created in setup_mongot,
# which gets called by ReplicaSetFixture::setup().
self.mongot = None
self.router_port = None
if "routerPort" in self.mongod_options:
self.router_port = fixturelib.get_next_port(job_num)
@ -98,7 +114,7 @@ class MongoDFixture(interface.Fixture, interface._DockerComposeInterface):
self.mongod = mongod
def _all_mongo_d_s(self):
def _all_mongo_d_s_t(self):
"""Return the standalone `mongod` `Process` instance."""
return [self]
@ -119,6 +135,23 @@ class MongoDFixture(interface.Fixture, interface._DockerComposeInterface):
self.logger.info("Waiting to connect to mongod on port %d.", self.port)
time.sleep(0.1) # Wait a little bit before trying again.
def setup_mongot(self):
mongot_options = {}
mongot_options["mongodHostAndPort"] = "localhost:" + str(self.port)
mongot_options["port"] = self.mongot_port
if "keyFile" not in self.mongod_options:
raise self.fixturelib.ServerFailure("Cannot launch mongot without providing a keyfile")
mongot_options["keyFile"] = self.mongod_options["keyFile"]
mongot = self.fixturelib.make_fixture("MongoTFixture", self.logger, self.job_num,
mongot_options=mongot_options)
mongot.setup()
self.mongot = mongot
self.mongot.await_ready()
def await_ready(self):
"""Block until the fixture can be used for testing."""
deadline = time.time() + MongoDFixture.AWAIT_READY_TIMEOUT_SECS
@ -173,6 +206,9 @@ class MongoDFixture(interface.Fixture, interface._DockerComposeInterface):
self.logger.warning(msg)
raise self.fixturelib.ServerFailure(msg)
if self.mongot is not None:
self.mongot._do_teardown(mode)
self.mongod.stop(mode)
exit_code = self.mongod.wait()
@ -272,6 +308,10 @@ class MongodLauncher(object):
if self.config.MONGOD_SET_PARAMETERS is not None:
suite_set_parameters.update(yaml.safe_load(self.config.MONGOD_SET_PARAMETERS))
if "mongotHost" in mongod_options:
suite_set_parameters["mongotHost"] = mongod_options.pop("mongotHost")
suite_set_parameters["searchIndexManagementHostAndPort"] = mongod_options.pop(
"searchIndexManagementHostAndPort")
# Some storage options are both a mongod option (as in config file option and its equivalent
# "--xyz" command line parameter) and a "--setParameter". In case of conflict, for instance
# due to the config fuzzer adding "xyz" as a "--setParameter" when the "--xyz" option is

View File

@ -10,6 +10,7 @@ ALLOWED_IMPORTS = [
"buildscripts.resmokelib.testing.fixtures.external",
"buildscripts.resmokelib.testing.fixtures.interface",
"buildscripts.resmokelib.testing.fixtures.fixturelib",
"buildscripts.resmokelib.testing.fixtures.mongot",
"buildscripts.resmokelib.multiversionconstants",
"buildscripts.resmokelib.utils",
"buildscripts.resmokelib.utils.registry",

View File

@ -0,0 +1,33 @@
// This test asserts that search e2e suites were correctly configured to spin up mongot(s) by
// checking that the mongotHost server parameter is set. A search index is created and a search
// query is ran to assert that no errors are thrown.
const coll = db.foo;
coll.drop()
coll.insert({a: -1, size: "small"})
coll.insert({a: -10, size: "medium", mood: "hungry"})
coll.insert({a: 100, size: "medium", mood: "very hungry"})
// A sanity check.
let result = coll.aggregate([{$match: {size: "medium"}}]).toArray();
assert.eq(result.length, 2);
// Confirm that mongod was launched with a connection string to mongot on localhost.
let paramOne = assert.commandWorked(db.adminCommand({getParameter: 1, "mongotHost": -1}));
assert(paramOne["mongotHost"].startsWith("localhost:"));
let paramTwo = assert.commandWorked(
db.adminCommand({getParameter: 1, "searchIndexManagementHostAndPort": -1}));
assert.eq(paramOne["mongotHost"], paramTwo["searchIndexManagementHostAndPort"]);
// TODO SERVER-86614 replace this with shell helper that waits for mongot index definitions to be
// stable.
let searchIndexResult = assert.commandWorked(db.runCommand(
{'createSearchIndexes': "foo", 'indexes': [{'definition': {'mappings': {'dynamic': true}}}]}));
assert.doesNotThrow(() => coll.aggregate([{"$listSearchIndexes": {}}]))
// TODO SERVER-86616 replace this $search query with shell helper and assert that results are
// correct.
let searchRes = assert.doesNotThrow(() => coll.aggregate([{
$search: {
exists: {
path: "mood",
}
}
}]));

View File

@ -0,0 +1 @@
Thiskeyisonlyforrunningthesuitewithauthenticationdontuseitinanytestsdirectly