From 7ec5a2ef1ac80d2a3b1715e75ac4e507330de4e6 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 15 Mar 2021 22:02:40 +0300 Subject: Add support for interactive-{mode,login} task request and interactive task manifest values --- libbbot/manifest.cxx | 89 +++++++++++++++++++++++++++++++++ libbbot/manifest.hxx | 69 ++++++++++++++++++++----- tests/manifest/task-request.testscript | 64 ++++++++++++++++++++++++ tests/manifest/task-response.testscript | 1 + tests/manifest/task.testscript | 16 ++++++ 5 files changed, 227 insertions(+), 12 deletions(-) diff --git a/libbbot/manifest.cxx b/libbbot/manifest.cxx index c01a84b..33b5046 100644 --- a/libbbot/manifest.cxx +++ b/libbbot/manifest.cxx @@ -65,6 +65,31 @@ namespace bbot else throw invalid_argument ("invalid result status '" + s + "'"); } + // interactive_mode + // + string + to_string (interactive_mode s) + { + switch (s) + { + case interactive_mode::false_: return "false"; + case interactive_mode::true_: return "true"; + case interactive_mode::both: return "both"; + } + + assert (false); + return string (); + } + + interactive_mode + to_interactive_mode (const string& s) + { + if (s == "false") return interactive_mode::false_; + else if (s == "true") return interactive_mode::true_; + else if (s == "both") return interactive_mode::both; + else throw invalid_argument ("invalid interactive mode '" + s + "'"); + } + // Utility functions // inline static bool @@ -246,6 +271,11 @@ namespace bbot if (nv.value != "1") bad_value ("unsupported format version"); + // Cache the interactive login manifest value and validate whether it's + // allowed later, after the interactive mode is parsed. + // + optional interactive_login_nv; + // Parse the task request manifest. // for (nv = p.next (); !nv.empty (); nv = p.next ()) @@ -288,6 +318,30 @@ namespace bbot e.what ()); } } + else if (n == "interactive-mode") + { + if (interactive_mode) + bad_name ("task request interactive mode redefinition"); + + try + { + interactive_mode = to_interactive_mode (v); + } + catch (const invalid_argument&) + { + bad_value (string ("invalid task request interactive mode")); + } + } + else if (n == "interactive-login") + { + if (interactive_login_nv) + bad_name ("task request interactive login redefinition"); + + if (v.empty ()) + bad_value ("empty task request interactive login"); + + interactive_login_nv = move (nv); + } else if (n == "fingerprint") { if (fingerprint) @@ -313,6 +367,22 @@ namespace bbot if (toolchain_version.empty ()) bad_value ("no task request toolchain version specified"); + if (effective_interactive_mode () != interactive_mode_type::false_) + { + if (!interactive_login_nv) + bad_value ("no task request interactive login specified"); + + interactive_login = move (interactive_login_nv->value); + } + else if (interactive_login_nv) + { + // Restore as bad_name() uses its line/column. + // + nv = move (*interactive_login_nv); + + bad_name ("interactive login specified for non-interactive mode"); + } + // Parse machine header manifests. // for (nv = p.next (); !nv.empty (); nv = p.next ()) @@ -338,6 +408,12 @@ namespace bbot s.next ("toolchain-name", toolchain_name); s.next ("toolchain-version", toolchain_version.string ()); + if (interactive_mode) + s.next ("interactive-mode", to_string (*interactive_mode)); + + if (interactive_login) + s.next ("interactive-login", *interactive_login); + if (fingerprint) s.next ("fingerprint", *fingerprint); @@ -607,6 +683,16 @@ namespace bbot if (warning_regex.empty ()) bad_value ("empty task warning regex"); } + else if (n == "interactive") + { + if (interactive) + bad_name ("task interactive value redefinition"); + + if (v.empty ()) + bad_value ("empty task interactive value"); + + interactive = move (v); + } else if (!iu) bad_name ("unknown name '" + n + "' in task manifest"); } @@ -704,6 +790,9 @@ namespace bbot serialize_list ("config", config); serialize_list ("warning-regex", warning_regex); + if (interactive) + s.next ("interactive", *interactive); + s.next ("", ""); // End of manifest. } diff --git a/libbbot/manifest.hxx b/libbbot/manifest.hxx index daee743..c3bb6ce 100644 --- a/libbbot/manifest.hxx +++ b/libbbot/manifest.hxx @@ -62,14 +62,40 @@ namespace bbot using machine_header_manifests = std::vector; + // Agent's capability to perform (non-)interactive builds. + // + enum class interactive_mode: std::uint8_t + { + false_, + true_, + both + }; + + LIBBBOT_EXPORT std::string + to_string (interactive_mode); + + LIBBBOT_EXPORT interactive_mode + to_interactive_mode (const std::string&); // May throw invalid_argument. + + inline std::ostream& + operator<< (std::ostream& os, interactive_mode m) + { + return os << to_string (m); + } + class LIBBBOT_EXPORT task_request_manifest { public: + using interactive_mode_type = bbot::interactive_mode; + std::string agent; std::string toolchain_name; butl::standard_version toolchain_version; + butl::optional interactive_mode; + butl::optional interactive_login; + // Agent's public key SHA256 fingerprint. // // @@ How the fingerpring for openssl public key will be produced? Seems @@ -82,16 +108,31 @@ namespace bbot machine_header_manifests machines; - task_request_manifest (std::string a, - std::string n, - butl::standard_version v, - butl::optional f, - machine_header_manifests m) - : agent (std::move (a)), - toolchain_name (std::move (n)), - toolchain_version (std::move (v)), - fingerprint (std::move (f)), - machines (std::move (m)) {} + // Return the effective interactive build mode. If the mode is not + // explicitly specified, then false is assumed. + // + interactive_mode_type + effective_interactive_mode () const noexcept + { + return interactive_mode + ? *interactive_mode + : interactive_mode_type::false_; + } + + task_request_manifest (std::string ag, + std::string tn, + butl::standard_version tv, + butl::optional im, + butl::optional il, + butl::optional fp, + machine_header_manifests ms) + : agent (std::move (ag)), + toolchain_name (std::move (tn)), + toolchain_version (std::move (tv)), + interactive_mode (std::move (im)), + interactive_login (std::move (il)), + fingerprint (std::move (fp)), + machines (std::move (ms)) {} public: task_request_manifest () = default; // VC export. @@ -146,6 +187,8 @@ namespace bbot // strings warning_regex; + butl::optional interactive; // Interactive build breakpoint. + strings unquoted_config () const; @@ -161,7 +204,8 @@ namespace bbot butl::target_triplet tg, butl::optional en, strings cf, - strings wr) + strings wr, + butl::optional ir) : name (std::move (nm)), version (std::move (vr)), repository (std::move (rl)), @@ -171,7 +215,8 @@ namespace bbot target (std::move (tg)), environment (std::move (en)), config (std::move (cf)), - warning_regex (std::move (wr)){} + warning_regex (std::move (wr)), + interactive (std::move (ir)) {} public: task_manifest () = default; // VC export. diff --git a/tests/manifest/task-request.testscript b/tests/manifest/task-request.testscript index 4b797f6..cee21fb 100644 --- a/tests/manifest/task-request.testscript +++ b/tests/manifest/task-request.testscript @@ -15,6 +15,8 @@ test.options += -tq agent: upsa toolchain-name: queue toolchain-version: 0.5.0 + interactive-mode: both + interactive-login: 10.5.0.1:5901 fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e : id: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 @@ -124,3 +126,65 @@ toolchain-name: queue toolchain-version: 0.5.0 fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e EOI + +: interactive +: +{ + : redefinition + : + { + : mode + : + $* <'stdin:3:1: error: task request interactive mode redefinition' == 1 + : 1 + interactive-mode: true + interactive-mode: both + EOI + + : login + : + $* <'stdin:3:1: error: task request interactive login redefinition' == 1 + : 1 + interactive-login: 10.5.0.1:5901 + interactive-login: 10.5.0.1:5901 + EOI + } + + : invalid + : + { + : mode + : + $* <'stdin:2:19: error: invalid task request interactive mode' == 1 + : 1 + interactive-mode: on + EOI + + : login + : + $* <'stdin:2:19: error: empty task request interactive login' == 1 + : 1 + interactive-login: + EOI + } + + : no-login + : + $* <'stdin:6:1: error: no task request interactive login specified' == 1 + : 1 + agent: upsa + toolchain-name: queue + toolchain-version: 0.5.0 + interactive-mode: both + EOI + + : unexpected-login + : + $* <'stdin:5:1: error: interactive login specified for non-interactive mode' == 1 + : 1 + agent: upsa + toolchain-name: queue + toolchain-version: 0.5.0 + interactive-login: 10.5.0.1:5901 + EOI +} diff --git a/tests/manifest/task-response.testscript b/tests/manifest/task-response.testscript index e7dbdb9..d486dda 100644 --- a/tests/manifest/task-response.testscript +++ b/tests/manifest/task-response.testscript @@ -80,6 +80,7 @@ test.options += -ts : invalid : { + : challenge : { diff --git a/tests/manifest/task.testscript b/tests/manifest/task.testscript index 65ecd29..b5ca66a 100644 --- a/tests/manifest/task.testscript +++ b/tests/manifest/task.testscript @@ -24,6 +24,7 @@ test.options += -t environment: lld config: config.cc.coptions=/Z7 config.cc.loptions=/DEBUG warning-regex: '^warning: ' '^.+: warning: ' + interactive: error EOF : no-config-regex-environment @@ -167,6 +168,14 @@ test.options += -t warning-regex: '^warning: ' warning-regex: '^.+: warning: ' EOI + + : interactive + : + $* <'stdin:3:1: error: task interactive value redefinition' == 1 + : 1 + interactive: error + interactive: warning + EOI } : invalid @@ -326,6 +335,13 @@ test.options += -t : 1 trust: abc EOI + + : interactive + : + $* <'stdin:2:13: error: empty task interactive value' == 1 + : 1 + interactive: + EOI } : unknown-name -- cgit v1.1