diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2023-12-07 10:59:10 +0100 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2023-12-11 15:41:58 +0100 |
commit | a1bdc438f3e17b0c30f3a53b0bc5e38ebb7bb936 (patch) | |
tree | dca0a5c292eb573d36888cc631e92f6ed4d74428 | |
parent | bcbfd1fc659df948899fa34e8a1af7fa6f7920e6 (diff) | |
download | justbuild-a1bdc438f3e17b0c30f3a53b0bc5e38ebb7bb936.tar.gz |
just-mrrc: support file options for the launcher functionality
When just-mr acts as a launcher, for most subcommand options the
"just args" entry in the rc files provides a convenient way to set
them. However, some options take a file as argument; for those it can
be desirable to set them without assuming a fixed file-system layout
and instead refer to logical roots, in particular the work space.
for the ones that refer to files, it is often desirable to have a potential
reference to the work space. Add this functionality.
-rw-r--r-- | share/man/just-mrrc.5.md | 18 | ||||
-rw-r--r-- | src/other_tools/just_mr/cli.hpp | 2 | ||||
-rw-r--r-- | src/other_tools/just_mr/launch.cpp | 10 | ||||
-rw-r--r-- | src/other_tools/just_mr/rc.cpp | 44 | ||||
-rw-r--r-- | src/other_tools/just_mr/utils.hpp | 9 | ||||
-rw-r--r-- | test/end-to-end/just-mr/defaults.sh | 72 |
6 files changed, 153 insertions, 2 deletions
diff --git a/share/man/just-mrrc.5.md b/share/man/just-mrrc.5.md index 559c4d5f..85c2ce75 100644 --- a/share/man/just-mrrc.5.md +++ b/share/man/just-mrrc.5.md @@ -109,8 +109,8 @@ The just-mrrc is given by a JSON object. - The value for the key *`"authentication"`* is a JSON object specifying client-side authentication options for **`just-mr`**. - For subkey *`"ca cert"`* the value is a single location object the path to - a TLS CA certificate. + For subkey *`"ca cert"`* the value is a single location object + specifying the path to a TLS CA certificate. For subkey *`"client cert"`* the value is a single location object specifying the path to a TLS client certificate. For subkey *`"client key"`* the value is a single location object specifying @@ -118,6 +118,14 @@ The just-mrrc is given by a JSON object. Each subkey value can be overwritten by its corresponding command-line argument. + - The value for the key *`"just files"`* is a JSON object. The keys correspond + to options that some **`just`** subcommands accept and require a file as + argument. For each key, the value is a list of location objects. When + **`just-mr`** is used as a launcher and the invoked subcommand is known to + support this option, this option is set in the **`just`** invocation with + the first matching entry, if any. The supported options are *`"config"`* + and *`endpoint-configuration`*. + - The value for the key *`"just args"`* is a JSON object. Its keys are **`just`** subcommands and its value is a JSON list of strings. For the corresponding subcommand, these strings are prefixed to the **`just`** @@ -153,6 +161,12 @@ An example just-mrrc file could look like the following: , "install": ["--remote-execution-property", "OS:Linux"] , "rebuild": ["--remote-execution-property", "OS:Linux"] } +, "just files": + { "config": + [ {"root": "workspace", "path": "etc/config.json"} + , {"root": "home", "path": ".just-config"} + ] + } } ``` diff --git a/src/other_tools/just_mr/cli.hpp b/src/other_tools/just_mr/cli.hpp index 3d7a8980..b4f6607d 100644 --- a/src/other_tools/just_mr/cli.hpp +++ b/src/other_tools/just_mr/cli.hpp @@ -80,6 +80,8 @@ struct MultiRepoJustSubCmdsArguments { std::optional<std::string> subcmd_name{std::nullopt}; std::vector<std::string> additional_just_args{}; std::unordered_map<std::string, std::vector<std::string>> just_args{}; + std::optional<std::filesystem::path> config{}; + std::optional<std::filesystem::path> endpoint_configuration{}; }; // corresponding to the similarly-named arguments in 'just' diff --git a/src/other_tools/just_mr/launch.cpp b/src/other_tools/just_mr/launch.cpp index 4e9403a8..2c771836 100644 --- a/src/other_tools/just_mr/launch.cpp +++ b/src/other_tools/just_mr/launch.cpp @@ -48,6 +48,7 @@ auto CallJust(std::optional<std::filesystem::path> const& config_file, bool use_launcher{false}; bool supports_defines{false}; bool supports_remote{false}; + bool supports_dispatch{false}; bool supports_cacert{false}; bool supports_client_auth{false}; std::optional<std::filesystem::path> mr_config_path{std::nullopt}; @@ -81,6 +82,7 @@ auto CallJust(std::optional<std::filesystem::path> const& config_file, use_launcher = kKnownJustSubcommands.at(*subcommand).launch; supports_defines = kKnownJustSubcommands.at(*subcommand).defines; supports_remote = kKnownJustSubcommands.at(*subcommand).remote; + supports_dispatch = kKnownJustSubcommands.at(*subcommand).dispatch; supports_cacert = kKnownJustSubcommands.at(*subcommand).cacert; supports_client_auth = kKnownJustSubcommands.at(*subcommand).client_auth; @@ -121,6 +123,10 @@ auto CallJust(std::optional<std::filesystem::path> const& config_file, cmd.emplace_back("--plain-log"); } if (supports_defines) { + if (just_cmd_args.config) { + cmd.emplace_back("-c"); + cmd.emplace_back(just_cmd_args.config->string()); + } auto overlay_config = Configuration(); for (auto const& s : common_args.defines) { try { @@ -153,6 +159,10 @@ auto CallJust(std::optional<std::filesystem::path> const& config_file, cmd.emplace_back("-r"); cmd.emplace_back(*common_args.remote_execution_address); } + if (supports_dispatch and just_cmd_args.endpoint_configuration) { + cmd.emplace_back("--endpoint-configuration"); + cmd.emplace_back(*just_cmd_args.endpoint_configuration); + } if (supports_remote and common_args.remote_serve_address) { cmd.emplace_back("--remote-serve-address"); cmd.emplace_back(*common_args.remote_serve_address); diff --git a/src/other_tools/just_mr/rc.cpp b/src/other_tools/just_mr/rc.cpp index 63e772bf..d8b8067a 100644 --- a/src/other_tools/just_mr/rc.cpp +++ b/src/other_tools/just_mr/rc.cpp @@ -103,6 +103,30 @@ namespace { std::filesystem::weakly_canonical( std::filesystem::absolute(root_path / base))); } + +[[nodiscard]] auto ReadOptionalLocationList( + ExpressionPtr const& location_list, + std::optional<std::filesystem::path> const& ws_root, + std::string const& argument_name) -> std::optional<std::filesystem::path> { + if (location_list->IsNone()) { + return std::nullopt; + } + if (not location_list->IsList()) { + Logger::Log(LogLevel::Error, + "Argument {} has to be a list, but found {}", + argument_name, + location_list->ToString()); + std::exit(kExitConfigError); + } + for (auto const& location : location_list->List()) { + auto p = ReadLocation(location, ws_root); + if (p and FileSystemManager::IsFile(p->first)) { + return p->first; + } + } + return std::nullopt; +} + } // namespace /// \brief Read just-mrrc file and set up various configs. Return the path to @@ -216,6 +240,26 @@ namespace { clargs->common.git_path = git->first; } } + // read the just file-arguments + auto just_files = rc_config["just files"]; + if (just_files.IsNotNull()) { + if (not just_files->IsMap()) { + Logger::Log(LogLevel::Error, + "Configration-file provided 'just files' has to be a " + "map, but found {}.", + just_files->ToString()); + std::exit(kExitConfigError); + } + auto files = Configuration(just_files); + clargs->just_cmd.config = ReadOptionalLocationList( + files["config"], + clargs->common.just_mr_paths->workspace_root, + "'config' in 'just files'"); + clargs->just_cmd.endpoint_configuration = ReadOptionalLocationList( + files["endpoint-configuration"], + clargs->common.just_mr_paths->workspace_root, + "'endpoint-configuration' in 'just files'"); + } // read additional just args; user can append, but does not overwrite auto just_args = rc_config["just args"]; if (just_args.IsNotNull()) { diff --git a/src/other_tools/just_mr/utils.hpp b/src/other_tools/just_mr/utils.hpp index 0fc18748..54abd3d5 100644 --- a/src/other_tools/just_mr/utils.hpp +++ b/src/other_tools/just_mr/utils.hpp @@ -50,6 +50,7 @@ struct JustSubCmdFlags { bool launch; // supports the local launcher arg bool defines; // supports defines arg bool remote; // supports remote exec args + bool dispatch; // supports dispatching of the remote-execution endpoint bool cacert; // supports CA cert arg bool client_auth; // supports client auth args }; @@ -62,6 +63,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = false, .defines = false, .remote = false, + .dispatch = false, .cacert = false, .client_auth = false}}, {"describe", @@ -70,6 +72,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = false, .defines = true, .remote = false, + .dispatch = false, .cacert = false, .client_auth = false}}, {"analyse", @@ -78,6 +81,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = false, .defines = true, .remote = true, + .dispatch = true, .cacert = false, .client_auth = false}}, {"build", @@ -86,6 +90,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = true, .defines = true, .remote = true, + .dispatch = true, .cacert = true, .client_auth = true}}, {"install", @@ -94,6 +99,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = true, .defines = true, .remote = true, + .dispatch = true, .cacert = true, .client_auth = true}}, {"rebuild", @@ -102,6 +108,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = true, .defines = true, .remote = true, + .dispatch = true, .cacert = true, .client_auth = true}}, {"install-cas", @@ -110,6 +117,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = false, .defines = false, .remote = true, + .dispatch = false, .cacert = true, .client_auth = true}}, {"gc", @@ -118,6 +126,7 @@ std::map<std::string, JustSubCmdFlags> const kKnownJustSubcommands{ .launch = false, .defines = false, .remote = false, + .dispatch = false, .cacert = false, .client_auth = false}}}; diff --git a/test/end-to-end/just-mr/defaults.sh b/test/end-to-end/just-mr/defaults.sh index 57b020f6..12ed5c5f 100644 --- a/test/end-to-end/just-mr/defaults.sh +++ b/test/end-to-end/just-mr/defaults.sh @@ -36,6 +36,10 @@ cat > "${SAMPLE_RC}" <<EOF , {"root": "system", "path": "${LOG_DIR#/}/rc2.log"} ] , "local launcher": ["env", "SET_IN_RC=true"] +, "just files": + { "config": [{"root": "workspace", "path": "sample-config.json"}] + , "endpoint-configuration": [{"root": "workspace", "path": "endpoint.json"}] + } } EOF cat "${SAMPLE_RC}" @@ -56,6 +60,8 @@ from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument("-C", dest="repository_config") +parser.add_argument("-c", "--config", dest="build_config") +parser.add_argument("--endpoint-configuration", dest="endpoint") parser.add_argument("--local-build-root", dest="local_build_root") parser.add_argument("-L","--local-launcher", dest="local_launcher") parser.add_argument("-f", "--log-file", dest="log_file", @@ -74,6 +80,18 @@ with open(os.path.join(target_dir, "log-limit"), "w") as f: f.write(json.dumps(options.log_limit)) with open(os.path.join(target_dir, "log-file"), "w") as f: f.write(json.dumps(options.log_file)) +if options.build_config: + with open(os.path.join(target_dir, "config"), "w") as f: + f.write(json.dumps(options.build_config)) +else: + if os.path.exists(os.path.join(target_dir, "config")): + os.unlink(os.path.join(target_dir, "config")) +if options.endpoint: + with open(os.path.join(target_dir, "endpoint"), "w") as f: + f.write(json.dumps(options.endpoint)) +else: + if os.path.exists(os.path.join(target_dir, "endpoint")): + os.unlink(os.path.join(target_dir, "endpoint")) with open(os.path.join(target_dir, "launcher"), "w") as f: if options.local_launcher: f.write(options.local_launcher) @@ -170,4 +188,58 @@ test $(jq '. == [ {"foo": "override", "baz": "baz"}] ' "${PARSE_DIR}/defines") = build -D '{"foo": "override"}' -D '{"x": "y"}' "${PARSE_DIR}" 2>&1 test $(jq '. == [ {"foo": "bar", "baz": "baz"}, {"foo": "override"}, {"x": "y"}] ' "${PARSE_DIR}/defines") = true +## -c + +# honored from rc-file if present +touch sample-config.json +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/config" ] + +# not honored for non-analysing subcommands +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" install-cas "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/config" ] && exit 1 || : + +# not considered an error if not present +rm -f sample-config.json +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/config" ] && exit 1 || : + +# not considered, if key not present in rc +cat > tmprc.json <<'EOF' +{"just files": {"unrelated": 123}} +EOF +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc tmprc.json build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/config" ] && exit 1 || : + +## --endpoint-configuration + +# honored from rc-file if present +touch endpoint.json +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/endpoint" ] + +# not honored for non-endpoint-specific subcommands +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" install-cas "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/endpoint" ] && exit 1 || : + +# not considered an error if not present +rm -f endpoint.json +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc "${SAMPLE_RC}" build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/endpoint" ] && exit 1 || : + +# not considered, if key not present in rc +cat > tmprc.json <<'EOF' +{"just files": {"unrelated": 123}} +EOF +"${JUST_MR}" --local-build-root "${LBR}" --just "${PARSE}" \ + --rc tmprc.json build "${PARSE_DIR}" 2>&1 +[ -f "${PARSE_DIR}/endpoint" ] && exit 1 || : + echo OK |