mirror of https://github.com/mongodb/mongo
SERVER-105426 Feature flag checks should default to using lastLTS FCV when the FCV is uninitialized (#40317)
GitOrigin-RevId: 892aaae0e10cb983ff69ed902c54fede2a56a784
This commit is contained in:
parent
cc000571a2
commit
f77e78090f
|
|
@ -460,12 +460,16 @@ void ExpressionContext::throwIfFeatureFlagIsNotEnabledOnFCV(
|
|||
// should check the lowest FCV. We are guaranteed that maxFeatureCompatibilityVersion will
|
||||
// always be greater than or equal to the last LTS. So we will check the last LTS.
|
||||
const auto fcv = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
|
||||
mongo::multiversion::FeatureCompatibilityVersion versionToCheck = fcv.getVersion();
|
||||
if (!fcv.isVersionInitialized()) {
|
||||
// (Generic FCV reference): This FCV reference should exist across LTS binary versions.
|
||||
versionToCheck = multiversion::GenericFCV::kLastLTS;
|
||||
} else if (maxFeatureCompatibilityVersion) {
|
||||
versionToCheck = *maxFeatureCompatibilityVersion;
|
||||
// (Generic FCV reference): This FCV reference should exist across LTS binary
|
||||
// versions.
|
||||
mongo::multiversion::FeatureCompatibilityVersion versionToCheck =
|
||||
multiversion::GenericFCV::kLastLTS;
|
||||
|
||||
// Ensure 'fcv' is initialized before calling 'getVersion()' to prevent an invariant
|
||||
// error.
|
||||
if (fcv.isVersionInitialized()) {
|
||||
versionToCheck =
|
||||
maxFeatureCompatibilityVersion ? *maxFeatureCompatibilityVersion : fcv.getVersion();
|
||||
}
|
||||
|
||||
uassert(ErrorCodes::QueryFeatureNotAllowed,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "mongo/bson/bsonmisc.h"
|
||||
#include "mongo/bson/bsonobjbuilder.h"
|
||||
#include "mongo/bson/timestamp.h"
|
||||
#include "mongo/db/feature_flag_test_gen.h"
|
||||
#include "mongo/db/logical_time.h"
|
||||
#include "mongo/db/namespace_string.h"
|
||||
#include "mongo/db/pipeline/expression_context.h"
|
||||
|
|
@ -237,5 +238,66 @@ TEST_F(ExpressionContextTest, DontInitializeUnreferencedVariables) {
|
|||
ASSERT_FALSE(expCtx->variables.hasValue(Variables::kUserRolesId));
|
||||
}
|
||||
|
||||
TEST_F(ExpressionContextTest, UseLastLTSFeatureFlagWhenFCVUninitialized) {
|
||||
auto opCtx = makeOperationContext();
|
||||
std::vector<BSONObj> pipeline;
|
||||
pipeline.push_back(BSON("$match" << BSON("a" << 1)));
|
||||
AggregateCommandRequest acr({} /*nss*/, pipeline);
|
||||
ResolvedNamespaceMap sm;
|
||||
auto expCtx = make_intrusive<ExpressionContext>(opCtx.get(),
|
||||
acr,
|
||||
nullptr /*collator*/,
|
||||
nullptr /*mongoProcessInterface*/,
|
||||
sm,
|
||||
boost::none /*collUUID*/);
|
||||
|
||||
const auto kOriginalFCV =
|
||||
serverGlobalParams.featureCompatibility.acquireFCVSnapshot().getVersion();
|
||||
ON_BLOCK_EXIT([&] { serverGlobalParams.mutableFCV.setVersion(kOriginalFCV); });
|
||||
// (Generic FCV reference): for testing only. This comment is required by linter.
|
||||
serverGlobalParams.mutableFCV.setVersion(
|
||||
multiversion::FeatureCompatibilityVersion::kUnsetDefaultLastLTSBehavior);
|
||||
|
||||
// If the FCV is uninitialized, we should check the feature flag is enabled on the lastLTS
|
||||
// version.
|
||||
// 'featureFlagSpoon' should be enabled, since it is a test feature flag that is always enabled
|
||||
// on the lastLTS version.
|
||||
ASSERT_DOES_NOT_THROW(
|
||||
expCtx->throwIfFeatureFlagIsNotEnabledOnFCV("foo", feature_flags::gFeatureFlagSpoon));
|
||||
|
||||
// 'featureFlagBlender' should not be enabled, since it is a test feature flag that is always
|
||||
// enabled on the latest version.
|
||||
ASSERT_THROWS_CODE(
|
||||
expCtx->throwIfFeatureFlagIsNotEnabledOnFCV("foo", feature_flags::gFeatureFlagBlender),
|
||||
DBException,
|
||||
ErrorCodes::QueryFeatureNotAllowed);
|
||||
}
|
||||
|
||||
TEST_F(ExpressionContextTest, UseLatestFeatureFlagWhenFCVInitialized) {
|
||||
auto opCtx = makeOperationContext();
|
||||
std::vector<BSONObj> pipeline;
|
||||
pipeline.push_back(BSON("$match" << BSON("a" << 1)));
|
||||
AggregateCommandRequest acr({} /*nss*/, pipeline);
|
||||
ResolvedNamespaceMap sm;
|
||||
auto expCtx = make_intrusive<ExpressionContext>(opCtx.get(),
|
||||
acr,
|
||||
nullptr /*collator*/,
|
||||
nullptr /*mongoProcessInterface*/,
|
||||
sm,
|
||||
boost::none /*collUUID*/);
|
||||
|
||||
const auto& fcvSnapshot = serverGlobalParams.featureCompatibility.acquireFCVSnapshot();
|
||||
ASSERT_TRUE(fcvSnapshot.isVersionInitialized());
|
||||
// (Generic FCV reference): for testing only. This comment is required by linter.
|
||||
ASSERT_TRUE(fcvSnapshot.isGreaterThanOrEqualTo(multiversion::GenericFCV::kLatest));
|
||||
|
||||
// Since the FCV is initialized and is the latest version, 'featureFlagSpoon', enabled on the
|
||||
// lastLTS, and 'featureFlagBlender', enabled on the latest version, should both be enabled.
|
||||
ASSERT_DOES_NOT_THROW(
|
||||
expCtx->throwIfFeatureFlagIsNotEnabledOnFCV("foo", feature_flags::gFeatureFlagSpoon));
|
||||
ASSERT_DOES_NOT_THROW(
|
||||
expCtx->throwIfFeatureFlagIsNotEnabledOnFCV("foo", feature_flags::gFeatureFlagBlender));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mongo
|
||||
|
|
|
|||
|
|
@ -708,6 +708,35 @@ TEST(SetupOptions, NonNumericSlowMsYAMLConfigOptionFailsToParse) {
|
|||
ASSERT_NOT_OK(parser.run(options, argv, &environment));
|
||||
}
|
||||
|
||||
TEST(SetupOptions, ProfileFilterDependsOnFeatureParsesSuccessfully) {
|
||||
OptionsParserTester parser;
|
||||
moe::Environment environment;
|
||||
moe::OptionSection options;
|
||||
|
||||
ASSERT_OK(::mongo::addGeneralServerOptions(&options));
|
||||
ASSERT_OK(::mongo::addNonGeneralServerOptions(&options));
|
||||
|
||||
std::vector<std::string> argv;
|
||||
argv.push_back("binaryname");
|
||||
argv.push_back("--config");
|
||||
argv.push_back("config.yaml");
|
||||
|
||||
// $toUUID depends on 'featureFlagBinDataConvert' under FCV 8.0. This filter should
|
||||
// successfully parse, even though we do not verify feature flags in any of these functions.
|
||||
auto filterObj = BSON("$expr" << BSON("$lt" << BSON_ARRAY(BSON("$toUUID" << 0) << 0.01)));
|
||||
parser.setConfig("config.yaml",
|
||||
"operationProfiling:\n"
|
||||
" filter: '{$expr: {$lt: [{$toUUID: 0}, 0.01]}}'\n");
|
||||
|
||||
ASSERT_OK(parser.run(options, argv, &environment));
|
||||
ASSERT_OK(::mongo::validateServerOptions(environment));
|
||||
ASSERT_OK(::mongo::canonicalizeServerOptions(&environment));
|
||||
ASSERT_OK(::mongo::setupServerOptions(argv));
|
||||
ASSERT_OK(::mongo::storeServerOptions(environment));
|
||||
|
||||
ASSERT_BSONOBJ_EQ(::mongo::serverGlobalParams.defaultProfileFilter.get(), filterObj);
|
||||
}
|
||||
|
||||
TEST(SetupOptions, SampleRateCommandLineParamParsesSuccessfully) {
|
||||
OptionsParserTester parser;
|
||||
moe::Environment environment;
|
||||
|
|
|
|||
Loading…
Reference in New Issue