diff options
author | Shaun Verch <shaun.verch@10gen.com> | 2013-10-10 10:53:56 -0400 |
---|---|---|
committer | Shaun Verch <shaun.verch@10gen.com> | 2013-10-23 19:41:30 -0400 |
commit | 4686f81fe1ad2dc700ab17748d96e9c24f824579 (patch) | |
tree | b3d16f6d6f49622bcafb1513c31c4e52b95037ea /src/mongo/util | |
parent | 0f9712f7a666699b83cee27fa7136ea92aa9e555 (diff) | |
download | mongo-4686f81fe1ad2dc700ab17748d96e9c24f824579.tar.gz |
SERVER-11144 Add attribute to affect what sources an option can have
Diffstat (limited to 'src/mongo/util')
-rw-r--r-- | src/mongo/util/options_parser/option_description.cpp | 5 | ||||
-rw-r--r-- | src/mongo/util/options_parser/option_description.h | 23 | ||||
-rw-r--r-- | src/mongo/util/options_parser/option_section.cpp | 12 | ||||
-rw-r--r-- | src/mongo/util/options_parser/option_section.h | 17 | ||||
-rw-r--r-- | src/mongo/util/options_parser/options_parser.cpp | 6 | ||||
-rw-r--r-- | src/mongo/util/options_parser/options_parser_test.cpp | 264 |
6 files changed, 315 insertions, 12 deletions
diff --git a/src/mongo/util/options_parser/option_description.cpp b/src/mongo/util/options_parser/option_description.cpp index 6129d68597d..a98b33f1d6c 100644 --- a/src/mongo/util/options_parser/option_description.cpp +++ b/src/mongo/util/options_parser/option_description.cpp @@ -167,5 +167,10 @@ namespace optionenvironment { return *this; } + OptionDescription& OptionDescription::setSources(OptionSources sources) { + _sources = sources; + return *this; + } + } // namespace optionenvironment } // namespace mongo diff --git a/src/mongo/util/options_parser/option_description.h b/src/mongo/util/options_parser/option_description.h index 56fadd93338..8068665b265 100644 --- a/src/mongo/util/options_parser/option_description.h +++ b/src/mongo/util/options_parser/option_description.h @@ -39,6 +39,18 @@ namespace optionenvironment { }; /** + * An OptionSources is an enum representing where an option can come from + */ + enum OptionSources { + SourceCommandLine = 1, + SourceINIConfig = 2, + SourceJSONConfig = 4, + SourceAllConfig = SourceINIConfig | SourceJSONConfig, + SourceAllLegacy = SourceINIConfig | SourceCommandLine, + SourceAll = SourceCommandLine | SourceINIConfig | SourceJSONConfig + }; + + /** * The OptionDescription and PositionalOptionDescription classes are containers for information * about the options we are expecting either on the command line or in config files. These * should be registered in an OptionSection instance and passed to an OptionsParser. @@ -56,7 +68,8 @@ namespace optionenvironment { _isVisible(true), _default(Value()), _implicit(Value()), - _isComposing(false) { } + _isComposing(false), + _sources(SourceAll) { } /* * The following functions are part of the chaining interface for option registration. See @@ -95,6 +108,12 @@ namespace optionenvironment { */ OptionDescription& composing(); + /* + * Specify the allowed sources for this option, such as CommandLine, JSONConfig, or + * INIConfig. The default is SourceAll which means the option can be present in any source + */ + OptionDescription& setSources(OptionSources sources); + std::string _dottedName; // Used for JSON config and in Environment std::string _singleName; // Used for boost command line and INI OptionType _type; // Storage type of the argument value, or switch type (bool) @@ -104,6 +123,8 @@ namespace optionenvironment { Value _default; // Value if option is not specified Value _implicit; // Value if option is specified with no argument bool _isComposing; // Aggregate values from different sources instead of overriding + OptionSources _sources; // Places where an option can be specified (current sources are + // command line, json config, and ini config) }; class PositionalOptionDescription { diff --git a/src/mongo/util/options_parser/option_section.cpp b/src/mongo/util/options_parser/option_section.cpp index bfd41d507b3..f6819549d9f 100644 --- a/src/mongo/util/options_parser/option_section.cpp +++ b/src/mongo/util/options_parser/option_section.cpp @@ -98,7 +98,9 @@ namespace optionenvironment { try { addOptionChaining(positionalOption._name, positionalOption._name, - positionalOption._type, "hidden description").hidden(); + positionalOption._type, "hidden description") + .hidden() + .setSources(SourceCommandLine); } catch (DBException &e) { return e.toStatus(); @@ -370,11 +372,15 @@ namespace optionenvironment { Status OptionSection::getBoostOptions(po::options_description* boostOptions, bool visibleOnly, - bool includeDefaults) const { + bool includeDefaults, + OptionSources sources) const { std::list<OptionDescription>::const_iterator oditerator; for (oditerator = _options.begin(); oditerator != _options.end(); oditerator++) { - if (!visibleOnly || (oditerator->_isVisible)) { + // Only include this option if it matches the sources we specified and the option is + // either visible or we are requesting hidden options + if ((!visibleOnly || (oditerator->_isVisible)) && + (oditerator->_sources & sources)) { std::auto_ptr<po::value_semantic> boostType; Status ret = typeToBoostType(&boostType, oditerator->_type, diff --git a/src/mongo/util/options_parser/option_section.h b/src/mongo/util/options_parser/option_section.h index 05d3a807c0f..9dfcefd66ee 100644 --- a/src/mongo/util/options_parser/option_section.h +++ b/src/mongo/util/options_parser/option_section.h @@ -79,14 +79,20 @@ namespace optionenvironment { * Add an option to this section, and returns a reference to an OptionDescription to allow * for chaining. * - * Example: + * Examples: * * options.addOptionChaining("option", "option", moe::String, "Chaining Registration") * .hidden().setDefault(moe::Value("default")) - * .setImplicit(moe::Value("implicit")).composing(); + * .setImplicit(moe::Value("implicit")); * - * This creates a hidden option that is composing and has default and implicit values. See - * the OptionDescription class for details on these attributes. + * This creates a hidden option that has default and implicit values. + * + * options.addOptionChaining("name", "name", moe::String, "Composing Option") + * .composing().sources(SourceAllConfig); + * + * This creates an option that is composing and can be specified only in config files. + * + * See the OptionDescription class for details on the supported attributes. * * throws DBException on errors, such as attempting to register an option with the same name * as another option. These represent programming errors that should not happen during @@ -110,7 +116,8 @@ namespace optionenvironment { // These functions are used by the OptionsParser to make calls into boost::program_options Status getBoostOptions(po::options_description* boostOptions, bool visibleOnly = false, - bool includeDefaults = false) const; + bool includeDefaults = false, + OptionSources = SourceAll) const; Status getBoostPositionalOptions( po::positional_options_description* boostPositionalOptions) const; diff --git a/src/mongo/util/options_parser/options_parser.cpp b/src/mongo/util/options_parser/options_parser.cpp index 96bda76e445..3725d7a7ffc 100644 --- a/src/mongo/util/options_parser/options_parser.cpp +++ b/src/mongo/util/options_parser/options_parser.cpp @@ -167,7 +167,7 @@ namespace optionenvironment { for(std::vector<OptionDescription>::const_iterator iterator = options_vector.begin(); iterator != options_vector.end(); iterator++) { - if (key == iterator->_dottedName) { + if (key == iterator->_dottedName && (iterator->_sources & SourceJSONConfig)) { return Status::OK(); } } @@ -463,7 +463,7 @@ namespace optionenvironment { po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); - Status ret = options.getBoostOptions(&boostOptions); + Status ret = options.getBoostOptions(&boostOptions, false, false, SourceCommandLine); if (!ret.isOK()) { return ret; } @@ -512,7 +512,7 @@ namespace optionenvironment { po::options_description boostOptions; po::variables_map vm; - Status ret = options.getBoostOptions(&boostOptions); + Status ret = options.getBoostOptions(&boostOptions, false, false, SourceINIConfig); if (!ret.isOK()) { return ret; } diff --git a/src/mongo/util/options_parser/options_parser_test.cpp b/src/mongo/util/options_parser/options_parser_test.cpp index 5171a33669e..1537c66f5c7 100644 --- a/src/mongo/util/options_parser/options_parser_test.cpp +++ b/src/mongo/util/options_parser/options_parser_test.cpp @@ -1867,4 +1867,268 @@ namespace { } } + TEST(OptionSources, SourceCommandLine) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceCommandLine); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"disallowed\" }"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=disallowed"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + } + + TEST(OptionSources, SourceINIConfig) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceINIConfig); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("disallowed"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"disallowed\" }"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + } + + TEST(OptionSources, SourceJSONConfig) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceJSONConfig); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("disallowed"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"allowed\" }"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=disallowed"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + } + + TEST(OptionSources, SourceAllConfig) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceAllConfig); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("disallowed"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"allowed\" }"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + } + + TEST(OptionSources, SourceAllLegacy) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceAllLegacy); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"disallowed\" }"); + + ASSERT_NOT_OK(parser.run(testOpts, argv, env_map, &environment)); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + } + + TEST(OptionSources, SourceAll) { + OptionsParserTester parser; + moe::Environment environment; + moe::Value value; + std::vector<std::string> argv; + std::map<std::string, std::string> env_map; + std::string parameter; + + moe::OptionSection testOpts; + testOpts.addOptionChaining("config", "config", moe::String, "Config file to parse"); + testOpts.addOptionChaining("parameter", "parameter", moe::String, "Parameter") + .setSources(moe::SourceAll); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--parameter"); + argv.push_back("allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.json"); + + parser.setConfig("config.json", "{ parameter : \"allowed\" }"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + + argv.clear(); + argv.push_back("binaryname"); + argv.push_back("--config"); + argv.push_back("config.ini"); + + parser.setConfig("config.ini", "parameter=allowed"); + + ASSERT_OK(parser.run(testOpts, argv, env_map, &environment)); + ASSERT_OK(environment.get(moe::Key("parameter"), &value)); + ASSERT_OK(value.get(¶meter)); + ASSERT_EQUALS(parameter, "allowed"); + } } // unnamed namespace |