summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bradford <david.bradford@mongodb.com>2022-05-17 01:04:31 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-05-17 12:57:34 +0000
commit5c8894d8e0fb53d556675b3eb7b3b434e2e21448 (patch)
tree2823c936952e5848d87a3ed2098f07b4c0cf5eaf
parent1a44e197ee6d2e8ebdec97f8fd817619e84aacaa (diff)
downloadmongo-5c8894d8e0fb53d556675b3eb7b3b434e2e21448.tar.gz
SERVER-65937: Support different fcv tags for lts and continuous multiversion tests
(cherry picked from commit 3b4067a108295b079c3d43027caffe2e2c66d7d0)
-rw-r--r--buildscripts/resmokelib/discovery/__init__.py12
-rw-r--r--buildscripts/resmokelib/multiversion/__init__.py1
-rw-r--r--buildscripts/resmokelib/multiversion/multiversion_service.py169
-rw-r--r--buildscripts/resmokelib/multiversionconstants.py84
-rw-r--r--buildscripts/tests/resmokelib/multiversion/__init__.py1
-rw-r--r--buildscripts/tests/resmokelib/multiversion/test_multiversion_service.py59
-rw-r--r--evergreen/generate_version.sh2
7 files changed, 252 insertions, 76 deletions
diff --git a/buildscripts/resmokelib/discovery/__init__.py b/buildscripts/resmokelib/discovery/__init__.py
index 02c6a206564..617eec6655e 100644
--- a/buildscripts/resmokelib/discovery/__init__.py
+++ b/buildscripts/resmokelib/discovery/__init__.py
@@ -6,6 +6,7 @@ from pydantic import BaseModel
from buildscripts.resmokelib import configure_resmoke
from buildscripts.resmokelib import suitesconfig
+from buildscripts.resmokelib.multiversion.multiversion_service import MultiversionService, MongoReleases, MongoVersion
from buildscripts.resmokelib.plugin import PluginInterface, Subcommand
from buildscripts.resmokelib.testing.suite import Suite
@@ -85,6 +86,8 @@ class MultiversionConfig(BaseModel):
last_versions: List[str]
requires_fcv_tag: str
+ requires_fcv_tag_lts: str
+ requires_fcv_tag_continuous: str
class MultiversionConfigSubcommand(Subcommand):
@@ -99,9 +102,16 @@ class MultiversionConfigSubcommand(Subcommand):
def determine_multiversion_config() -> MultiversionConfig:
"""Discover the current multiversion configuration."""
from buildscripts.resmokelib import multiversionconstants
+ multiversion_service = MultiversionService(
+ mongo_version=MongoVersion.from_yaml_file(multiversionconstants.MONGO_VERSION_YAML),
+ mongo_releases=MongoReleases.from_yaml_file(multiversionconstants.RELEASES_YAML),
+ )
+ fcv_constants = multiversion_service.calculate_fcv_constants()
return MultiversionConfig(
last_versions=multiversionconstants.OLD_VERSIONS,
- requires_fcv_tag=multiversionconstants.REQUIRES_FCV_TAG,
+ requires_fcv_tag=fcv_constants.get_fcv_tag_list(),
+ requires_fcv_tag_lts=fcv_constants.get_lts_fcv_tag_list(),
+ requires_fcv_tag_continuous=fcv_constants.get_continuous_fcv_tag_list(),
)
diff --git a/buildscripts/resmokelib/multiversion/__init__.py b/buildscripts/resmokelib/multiversion/__init__.py
new file mode 100644
index 00000000000..4b7a2bb941b
--- /dev/null
+++ b/buildscripts/resmokelib/multiversion/__init__.py
@@ -0,0 +1 @@
+"""Empty."""
diff --git a/buildscripts/resmokelib/multiversion/multiversion_service.py b/buildscripts/resmokelib/multiversion/multiversion_service.py
new file mode 100644
index 00000000000..0f8ff484159
--- /dev/null
+++ b/buildscripts/resmokelib/multiversion/multiversion_service.py
@@ -0,0 +1,169 @@
+"""A service for working with multiversion testing."""
+from __future__ import annotations
+
+import re
+from bisect import bisect_left, bisect_right
+from typing import List, NamedTuple, Optional
+
+from packaging.version import Version
+from pydantic import BaseModel, Field
+import yaml
+
+# These values must match the include paths for artifacts.tgz in evergreen.yml.
+MONGO_VERSION_YAML = ".resmoke_mongo_version.yml"
+RELEASES_YAML = ".resmoke_mongo_release_values.yml"
+VERSION_RE = re.compile(r'^[0-9]+\.[0-9]+')
+
+
+def tag_str(version: Version) -> str:
+ """Return a tag for the given version."""
+ return 'requires_fcv_{}{}'.format(version.major, version.minor)
+
+
+class FcvConstantValues(NamedTuple):
+ """
+ Object to hold the calculated FCV constants.
+
+ * latest: Latest FCV.
+ * last_continuous: Last continuous FCV.
+ * last_lts: Last LTS FCV.
+ * requires_fcv_tag_list: List of FCVs that we need to generate a tag for against LTS versions.
+ * requires_fcv_tag_list_continuous: List of FCVs that we need to generate a tag for against
+ continuous versions.
+ * fcvs_less_than_latest: List of all FCVs that are less than latest, starting from v4.0.
+ """
+
+ latest: Version
+ last_continuous: Version
+ last_lts: Version
+ requires_fcv_tag_list: List[Version]
+ requires_fcv_tag_list_continuous: List[Version]
+ fcvs_less_than_latest: List[Version]
+
+ def get_fcv_tag_list(self) -> str:
+ """Get a comma joined string of all the fcv tags."""
+ return ",".join([tag_str(tag) for tag in self.requires_fcv_tag_list])
+
+ def get_lts_fcv_tag_list(self) -> str:
+ """Get a comma joined string of all the LTS fcv tags."""
+ # Note: the LTS tag list is the default used above, so this function is the same as
+ # `get_fcv_tag_list`. This function was added to make it explicit when we want to use
+ # the LTS version vs the default.
+ return ",".join([tag_str(tag) for tag in self.requires_fcv_tag_list])
+
+ def get_continuous_fcv_tag_list(self) -> str:
+ """Get a comma joined string of all the continuous fcv tags."""
+ return ",".join([tag_str(tag) for tag in self.requires_fcv_tag_list_continuous])
+
+ def get_latest_tag(self) -> str:
+ """Get a string version of the latest FCV."""
+ return tag_str(self.latest)
+
+
+class MongoVersion(BaseModel):
+ """
+ The mongo version being tested.
+
+ * mongo_version: The mongo version being tested.
+ """
+
+ mongo_version: str
+
+ @classmethod
+ def from_yaml_file(cls, yaml_file: str) -> MongoVersion:
+ """
+ Read the mongo version from the given yaml file.
+
+ :param yaml_file: Path to yaml file.
+ :return: MongoVersion read from file.
+ """
+ mongo_version_yml_file = open(yaml_file, 'r')
+ return cls(**yaml.safe_load(mongo_version_yml_file))
+
+ def get_version(self) -> Version:
+ """Get the Version representation of the mongo version being tested."""
+ version_match = VERSION_RE.match(self.mongo_version)
+ if version_match is None:
+ raise ValueError(
+ f"Could not determine version from mongo version string '{self.mongo_version}'")
+ return Version(version_match.group(0))
+
+
+class MongoReleases(BaseModel):
+ """
+ Information about the FCVs and LTS release version since v4.0.
+
+ * feature_compatibility_version: All FCVs starting with 4.0.
+ * long_term_support_releases: All LTS releases starting with 4.0.
+ * generate_fcv_lower_bound_override: Extend FCV generation down to the previous value of last
+ LTS.
+ """
+
+ feature_compatibility_versions: List[str] = Field(alias="featureCompatibilityVersions")
+ long_term_support_releases: List[str] = Field(alias="longTermSupportReleases")
+ generate_fcv_lower_bound_override: Optional[str] = Field(None,
+ alias="generateFCVLowerBoundOverride")
+
+ @classmethod
+ def from_yaml_file(cls, yaml_file: str) -> MongoReleases:
+ """
+ Read the mongo release information from the given yaml file.
+
+ :param yaml_file: Path to yaml file.
+ :return: MongoReleases read from file.
+ """
+
+ mongo_releases_file = open(yaml_file, 'r')
+ return cls(**yaml.safe_load(mongo_releases_file))
+
+ def get_fcv_versions(self) -> List[Version]:
+ """Get the Version representation of all fcv versions."""
+ return [Version(fcv) for fcv in self.feature_compatibility_versions]
+
+ def get_lts_versions(self) -> List[Version]:
+ """Get the Version representation of the lts versions."""
+ return [Version(fcv) for fcv in self.long_term_support_releases]
+
+
+class MultiversionService:
+ """A service for working with multiversion information."""
+
+ def __init__(self, mongo_version: MongoVersion, mongo_releases: MongoReleases) -> None:
+ """
+ Initialize the service.
+
+ :param mongo_version: Contents of the Mongo Version file.
+ :param mongo_releases: Contents of the Mongo Releases file.
+ """
+ self.mongo_version = mongo_version
+ self.mongo_releases = mongo_releases
+
+ def calculate_fcv_constants(self) -> FcvConstantValues:
+ """Calculate multiversion constants from data files."""
+ latest = self.mongo_version.get_version()
+ fcvs = self.mongo_releases.get_fcv_versions()
+ lts = self.mongo_releases.get_lts_versions()
+ lower_bound_override = self.mongo_releases.generate_fcv_lower_bound_override
+
+ # Highest release less than latest.
+ last_continuous = fcvs[bisect_left(fcvs, latest) - 1]
+
+ # Highest LTS release less than latest.
+ last_lts = lts[bisect_left(lts, latest) - 1]
+
+ # Normally, this list includes all FCVs greater than last LTS, up to latest.
+ # However, if we have 'generateFCVLowerBoundOverride' set in releases.yml, we will
+ # extend the lower bound to also include the previous value of lastLTS.
+ lts_cutoff = last_lts
+ if lower_bound_override is not None:
+ lts_cutoff = Version(lower_bound_override)
+ requires_fcv_tag_list = fcvs[bisect_right(fcvs, lts_cutoff):bisect_right(fcvs, latest)]
+ requires_fcv_tag_list_continuous = [latest]
+
+ # All FCVs less than latest.
+ fcvs_less_than_latest = fcvs[:bisect_left(fcvs, latest)]
+
+ return FcvConstantValues(latest=latest, last_continuous=last_continuous, last_lts=last_lts,
+ requires_fcv_tag_list=requires_fcv_tag_list,
+ requires_fcv_tag_list_continuous=requires_fcv_tag_list_continuous,
+ fcvs_less_than_latest=fcvs_less_than_latest)
diff --git a/buildscripts/resmokelib/multiversionconstants.py b/buildscripts/resmokelib/multiversionconstants.py
index 0ff3b42b56f..5cf8df73aa0 100644
--- a/buildscripts/resmokelib/multiversionconstants.py
+++ b/buildscripts/resmokelib/multiversionconstants.py
@@ -1,20 +1,17 @@
"""FCV and Server binary version constants used for multiversion testing."""
-
-from bisect import bisect_left, bisect_right
import os
-import re
import shutil
from subprocess import call, CalledProcessError, check_output, STDOUT, DEVNULL
import structlog
-import yaml
-from packaging.version import Version
try:
# when running resmoke
+ from buildscripts.resmokelib.multiversion.multiversion_service import MongoReleases, MongoVersion, MultiversionService
from buildscripts.resmokelib.multiversionsetupconstants import USE_EXISTING_RELEASES_FILE
except ImportError:
# when running db-contrib-tool
from multiversionsetupconstants import USE_EXISTING_RELEASES_FILE
+ from multiversion.multiversion_service import MongoReleases, MongoVersion, MultiversionService
LOGGER = structlog.getLogger(__name__)
@@ -76,83 +73,22 @@ else:
"Skipping generating releases file since the --useExistingReleasesFile flag has been set")
-class FCVConstantValues(object):
- """Object to hold the calculated FCV constants."""
-
- def __init__(self, latest, last_continuous, last_lts, requires_fcv_tag_list,
- fcvs_less_than_latest):
- """
- Initialize the object.
-
- :param latest: Latest FCV.
- :param last_continuous: Last continuous FCV.
- :param last_lts: Last LTS FCV.
- :param requires_fcv_tag_list: List of FCVs that we need to generate a tag for.
- :param fcvs_less_than_latest: List of all FCVs that are less than latest, starting from v4.0.
- """
- self.latest = latest
- self.last_continuous = last_continuous
- self.last_lts = last_lts
- self.requires_fcv_tag_list = requires_fcv_tag_list
- self.fcvs_less_than_latest = fcvs_less_than_latest
-
-
-def calculate_fcv_constants():
- """Calculate multiversion constants from data files."""
- mongo_version_yml_file = open(MONGO_VERSION_YAML, 'r')
- mongo_version_yml = yaml.safe_load(mongo_version_yml_file)
- mongo_version = mongo_version_yml['mongo_version']
- latest = Version(re.match(r'^[0-9]+\.[0-9]+', mongo_version).group(0))
-
- releases_yml_file = open(RELEASES_YAML, 'r')
- releases_yml = yaml.safe_load(releases_yml_file)
-
- fcvs = releases_yml['featureCompatibilityVersions']
- fcvs = list(map(Version, fcvs))
- lts = releases_yml['longTermSupportReleases']
- lts = list(map(Version, lts))
- lower_bound_override = releases_yml.get('generateFCVLowerBoundOverride')
-
- mongo_version_yml_file.close()
- releases_yml_file.close()
-
- # Highest release less than latest.
- last_continuous = fcvs[bisect_left(fcvs, latest) - 1]
-
- # Highest LTS release less than latest.
- last_lts = lts[bisect_left(lts, latest) - 1]
-
- # Normally, this list includes all FCVs greater than last LTS, up to latest.
- # However, if we have 'generateFCVLowerBoundOverride' set in releases.yml, we will
- # extend the lower bound to also include the prevous value of lastLTS.
- lts_cutoff = last_lts
- if lower_bound_override is not None:
- lts_cutoff = Version(lower_bound_override)
- requires_fcv_tag_list = fcvs[bisect_right(fcvs, lts_cutoff):bisect_right(fcvs, latest)]
-
- # All FCVs less than latest.
- fcvs_less_than_latest = fcvs[:bisect_left(fcvs, latest)]
-
- return FCVConstantValues(latest, last_continuous, last_lts, requires_fcv_tag_list,
- fcvs_less_than_latest)
-
-
def version_str(version):
"""Return a string of the given version in 'MAJOR.MINOR' form."""
return '{}.{}'.format(version.major, version.minor)
-def tag_str(version):
- """Return a tag for the given version."""
- return 'requires_fcv_{}{}'.format(version.major, version.minor)
-
-
def evg_project_str(version):
"""Return the evergreen project name for the given version."""
return 'mongodb-mongo-v{}.{}'.format(version.major, version.minor)
-fcv_constants = calculate_fcv_constants()
+multiversion_service = MultiversionService(
+ mongo_version=MongoVersion.from_yaml_file(MONGO_VERSION_YAML),
+ mongo_releases=MongoReleases.from_yaml_file(RELEASES_YAML),
+)
+
+fcv_constants = multiversion_service.calculate_fcv_constants()
LAST_LTS_BIN_VERSION = version_str(fcv_constants.last_lts)
LAST_CONTINUOUS_BIN_VERSION = version_str(fcv_constants.last_continuous)
@@ -169,11 +105,11 @@ LAST_LTS_MONGO_BINARY = "mongo-" + LAST_LTS_BIN_VERSION
LAST_LTS_MONGOD_BINARY = "mongod-" + LAST_LTS_BIN_VERSION
LAST_LTS_MONGOS_BINARY = "mongos-" + LAST_LTS_BIN_VERSION
-REQUIRES_FCV_TAG_LATEST = tag_str(fcv_constants.latest)
+REQUIRES_FCV_TAG_LATEST = fcv_constants.get_latest_tag()
# Generate tags for all FCVS in (lastLTS, latest], or (lowerBoundOverride, latest] if requested.
# All multiversion tests should be run with these tags excluded.
-REQUIRES_FCV_TAG = ",".join([tag_str(fcv) for fcv in fcv_constants.requires_fcv_tag_list])
+REQUIRES_FCV_TAG = fcv_constants.get_fcv_tag_list()
# Generate evergreen project names for all FCVs less than latest.
EVERGREEN_PROJECTS = ['mongodb-mongo-master']
diff --git a/buildscripts/tests/resmokelib/multiversion/__init__.py b/buildscripts/tests/resmokelib/multiversion/__init__.py
new file mode 100644
index 00000000000..4b7a2bb941b
--- /dev/null
+++ b/buildscripts/tests/resmokelib/multiversion/__init__.py
@@ -0,0 +1 @@
+"""Empty."""
diff --git a/buildscripts/tests/resmokelib/multiversion/test_multiversion_service.py b/buildscripts/tests/resmokelib/multiversion/test_multiversion_service.py
new file mode 100644
index 00000000000..1a067f1ff15
--- /dev/null
+++ b/buildscripts/tests/resmokelib/multiversion/test_multiversion_service.py
@@ -0,0 +1,59 @@
+"""Unit tests for multiversion_service.py."""
+from unittest import TestCase
+
+from packaging.version import Version
+
+import buildscripts.resmokelib.multiversion.multiversion_service as under_test
+
+# pylint: disable=missing-docstring,invalid-name
+
+
+class TestTagStr(TestCase):
+ def test_require_fcv_tag_should_be_returned(self):
+ self.assertEqual(under_test.tag_str(Version("6.0")), "requires_fcv_60")
+ self.assertEqual(under_test.tag_str(Version("5.3")), "requires_fcv_53")
+ self.assertEqual(under_test.tag_str(Version("31.41")), "requires_fcv_3141")
+
+
+class TestGetVersion(TestCase):
+ def test_version_should_be_extracted(self):
+ mongo_version = under_test.MongoVersion(mongo_version="6.0.0-rc5-18-gbcdfaa9035b")
+
+ self.assertEqual(mongo_version.get_version(), Version("6.0"))
+
+ def test_incompatible_version_should_raise_an_exception(self):
+ mongo_version = under_test.MongoVersion(mongo_version="not_a_version")
+
+ with self.assertRaises(ValueError):
+ mongo_version.get_version()
+
+
+class TestCalculateFcvConstants(TestCase):
+ def test_fcv_constants_should_be_accurate_for_lts_testing(self):
+ mongo_version = under_test.MongoVersion(mongo_version="6.0")
+ mongo_releases = under_test.MongoReleases(
+ **{
+ "featureCompatibilityVersions": [
+ "4.0", "4.2", "4.4", "4.7", "4.8", "4.9", "5.0", "5.1", "5.2", "5.3", "6.0",
+ "100.0"
+ ],
+ "longTermSupportReleases": ["4.0", "4.2", "4.4", "5.0"],
+ })
+
+ multiversion_service = under_test.MultiversionService(
+ mongo_version=mongo_version,
+ mongo_releases=mongo_releases,
+ )
+
+ fcv_constants = multiversion_service.calculate_fcv_constants()
+
+ self.assertEqual(fcv_constants.latest, Version("6.0"))
+ self.assertEqual(fcv_constants.last_continuous, Version("5.3"))
+ self.assertEqual(fcv_constants.last_lts, Version("5.0"))
+ self.assertEqual(fcv_constants.requires_fcv_tag_list,
+ [Version(v) for v in ["5.1", "5.2", "5.3", "6.0"]])
+ self.assertEqual(fcv_constants.requires_fcv_tag_list_continuous, [Version("6.0")])
+ self.assertEqual(fcv_constants.fcvs_less_than_latest, [
+ Version(v)
+ for v in ["4.0", "4.2", "4.4", "4.7", "4.8", "4.9", "5.0", "5.1", "5.2", "5.3"]
+ ])
diff --git a/evergreen/generate_version.sh b/evergreen/generate_version.sh
index 028b7ad923b..db38741fbbd 100644
--- a/evergreen/generate_version.sh
+++ b/evergreen/generate_version.sh
@@ -6,7 +6,7 @@ cd src
set -o errexit
set -o verbose
-curl -L https://github.com/mongodb/mongo-task-generator/releases/download/v0.3.4/mongo-task-generator --output mongo-task-generator
+curl -L https://github.com/mongodb/mongo-task-generator/releases/download/v0.3.6/mongo-task-generator --output mongo-task-generator
chmod +x mongo-task-generator
activate_venv