From ed8e64ca8525872c97f9331cb5c882b40864b84e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 8 Mar 2024 20:24:35 +0300 Subject: Add support for build auxiliary machines related manifest values --- libbbot/manifest.cxx | 145 +++++++++++++++++++++++++++++++ libbbot/manifest.hxx | 81 ++++++++++++++++- tests/manifest/machine-header.testscript | 18 ++++ tests/manifest/task-request.testscript | 16 ++++ tests/manifest/task.testscript | 30 +++++++ 5 files changed, 288 insertions(+), 2 deletions(-) diff --git a/libbbot/manifest.cxx b/libbbot/manifest.cxx index be642a0..ab392e4 100644 --- a/libbbot/manifest.cxx +++ b/libbbot/manifest.cxx @@ -7,11 +7,13 @@ #include #include #include // isxdigit() +#include // numeric_limits #include #include #include // size_t #include // move() #include // uint64_t +#include // strtoull() #include // find_if() #include // invalid_argument @@ -37,6 +39,29 @@ namespace bbot using butl::optional; + // machine_role + // + string + to_string (machine_role r) + { + switch (r) + { + case machine_role::build: return "build"; + case machine_role::auxiliary: return "auxiliary"; + } + + assert (false); + return string (); + } + + machine_role + to_machine_role (const string& s) + { + if (s == "build") return machine_role::build; + else if (s == "auxiliary") return machine_role::auxiliary; + else throw invalid_argument ("invalid machine role '" + s + '\''); + } + // result_status // string @@ -134,6 +159,29 @@ namespace bbot return true; } + // Return nullopt if the string is not a valid 64-bit unsigned integer. + // + static optional + parse_uint64 (const string& s) + { + if (!s.empty () && s[0] != '-' && s[0] != '+') // strtoull() allows these. + { + const char* b (s.c_str ()); + char* e (nullptr); + errno = 0; // We must clear it according to POSIX. + uint64_t v (strtoull (b, &e, 10)); // Can't throw. + + if (errno != ERANGE && + e == b + s.size () && + v <= numeric_limits::max ()) + { + return static_cast (v); + } + } + + return nullopt; + } + // machine_header_manifest // machine_header_manifest:: @@ -207,6 +255,40 @@ namespace bbot summary = move (v); } + else if (n == "role") + { + if (role) + bad_name ("machine role redefinition"); + + try + { + role = to_machine_role (v); + } + catch (const invalid_argument& e) + { + bad_value (e.what ()); + } + } + else if (n == "ram-minimum") + { + if (ram_minimum) + bad_name ("machine minimum RAM redefinition"); + + ram_minimum = parse_uint64 (v); + + if (!ram_minimum) + bad_value ("machine minimum RAM should be 64-bit unsigned integer"); + } + else if (n == "ram-maximum") + { + if (ram_maximum) + bad_name ("machine maximum RAM redefinition"); + + ram_maximum = parse_uint64 (v); + + if (!ram_maximum) + bad_value ("machine maximum RAM should be 64-bit unsigned integer"); + } else { switch (m) @@ -247,6 +329,15 @@ namespace bbot s.next ("name", name); s.next ("summary", summary); + if (role) + s.next ("role", to_string (*role)); + + if (ram_minimum) + s.next ("ram-minimum", std::to_string (*ram_minimum)); + + if (ram_maximum) + s.next ("ram-maximum", std::to_string (*ram_maximum)); + if (end_of_manifest) s.next ("", ""); // End of manifest. } @@ -358,6 +449,17 @@ namespace bbot fingerprint = move (v); } + else if (n == "auxiliary-ram") + { + if (auxiliary_ram) + bad_name ("auxiliary machines RAM limit redefinition"); + + auxiliary_ram = parse_uint64 (v); + + if (!auxiliary_ram) + bad_value ( + "auxiliary machines RAM limit should be 64-bit unsigned integer"); + } else if (!iu) bad_name ("unknown name '" + n + "' in task request manifest"); } @@ -423,6 +525,9 @@ namespace bbot if (fingerprint) s.next ("fingerprint", *fingerprint); + if (auxiliary_ram) + s.next ("auxiliary-ram", std::to_string (*auxiliary_ram)); + s.next ("", ""); // End of manifest. for (const machine_header_manifest& m: machines) @@ -644,6 +749,26 @@ namespace bbot machine = move (v); } + else if (n == "auxiliary-machine" || + (n.size () > 18 && n.compare (0, 18, "auxiliary-machine-") == 0)) + { + if (v.empty ()) + bad_value ("empty task auxiliary machine name"); + + auxiliary_machine m {move (v), + n.size () > 18 ? string (n, 18) : string ()}; + + if (find_if (auxiliary_machines.begin (), auxiliary_machines.end (), + [&m] (const auxiliary_machine& am) + { + return am.environment_name == m.environment_name; + }) != auxiliary_machines.end ()) + { + bad_name ("task auxiliary machine environment redefinition"); + } + + auxiliary_machines.push_back (move (m)); + } else if (n == "target") { if (!target.empty ()) @@ -668,6 +793,16 @@ namespace bbot environment = move (v); } + else if (n == "auxiliary-environment") + { + if (auxiliary_environment) + bad_name ("task auxiliary environment redefinition"); + + if (v.empty ()) + bad_value ("empty task auxiliary environment"); + + auxiliary_environment = move (v); + } else if (n == "config" || // @@ TMP Until toolchain 0.16.0 is released. n == "target-config") { @@ -815,11 +950,21 @@ namespace bbot s.next ("dependency-checksum", *dependency_checksum); s.next ("machine", machine); + + for (const auxiliary_machine& am: auxiliary_machines) + s.next ((!am.environment_name.empty () + ? "auxiliary-machine-" + am.environment_name + : "auxiliary-machine"), + am.name); + s.next ("target", target.string ()); if (environment) s.next ("environment", *environment); + if (auxiliary_environment) + s.next ("auxiliary-environment", *auxiliary_environment); + // Serialize an optional value of the strings type as a space-separated // string list. // diff --git a/libbbot/manifest.hxx b/libbbot/manifest.hxx index 5807aed..a815d3e 100644 --- a/libbbot/manifest.hxx +++ b/libbbot/manifest.hxx @@ -6,6 +6,7 @@ #include #include +#include // uint*_t #include #include @@ -24,15 +25,57 @@ namespace bbot { using strings = std::vector; + // The machine's role. + // + enum class machine_role: std::uint8_t + { + build, + auxiliary + }; + + LIBBBOT_EXPORT std::string + to_string (machine_role); + + LIBBBOT_EXPORT machine_role + to_machine_role (const std::string&); // May throw invalid_argument. + + inline std::ostream& + operator<< (std::ostream& os, machine_role r) + { + return os << to_string (r); + } + class LIBBBOT_EXPORT machine_header_manifest { public: std::string id; std::string name; std::string summary; + butl::optional role; + butl::optional ram_minimum; // In KiB. + butl::optional ram_maximum; // In KiB. - machine_header_manifest (std::string i, std::string n, std::string s) - : id (std::move (i)), name (std::move (n)), summary (std::move (s)) {} + // Return the effective machine role. If the role is not explicitly + // specified, then the build role is assumed. + // + machine_role + effective_role () const noexcept + { + return role ? *role : machine_role::build; + } + + machine_header_manifest (std::string i, + std::string n, + std::string s, + butl::optional r, + butl::optional rmn, + butl::optional rmx) + : id (std::move (i)), + name (std::move (n)), + summary (std::move (s)), + role (r), + ram_minimum (rmn), + ram_maximum (rmx) {} public: machine_header_manifest () = default; // VC export. @@ -106,6 +149,8 @@ namespace bbot // butl::optional fingerprint; + butl::optional auxiliary_ram; // In KiB. + machine_header_manifests machines; // Return the effective interactive build mode. If the mode is not @@ -125,6 +170,7 @@ namespace bbot butl::optional im, butl::optional il, butl::optional fp, + butl::optional ar, machine_header_manifests ms) : agent (std::move (ag)), toolchain_name (std::move (tn)), @@ -132,6 +178,7 @@ namespace bbot interactive_mode (std::move (im)), interactive_login (std::move (il)), fingerprint (std::move (fp)), + auxiliary_ram (ar), machines (std::move (ms)) {} public: @@ -149,6 +196,14 @@ namespace bbot bpkg::version version; }; + // Note: corresponds to build_auxiliary in the package manifest. + // + struct auxiliary_machine + { + std::string name; + std::string environment_name; + }; + class LIBBBOT_EXPORT task_manifest { public: @@ -174,10 +229,28 @@ namespace bbot std::string machine; // Build machine to use for building the package. + // The list of build auxiliary machines. + // + // Note that all entries in this list must have distinct environment names + // (with empty name being one of the possibilities). + // + // Also note that some auxiliary machines can potentially be used by the + // main package and some by the test packages. It is such package author's + // responsibility to make sure that the environment names specified in + // multiple package manifests do not clash. It is bbot controller's + // responsibility to verify that there is no clash, aborting the task if + // there is. + // + std::vector auxiliary_machines; + butl::target_triplet target; // Build target. butl::optional environment; // Build environment name. + // The environment variables describing the auxiliary machines. + // + butl::optional auxiliary_environment; + // Build system configuration variables (in addition to build environment // configuration variables). // @@ -218,8 +291,10 @@ namespace bbot butl::small_vector ts, butl::optional dc, std::string mn, + std::vector ams, butl::target_triplet tg, butl::optional en, + butl::optional ae, strings tc, std::string pc, butl::optional ht, @@ -234,8 +309,10 @@ namespace bbot tests (std::move (ts)), dependency_checksum (std::move (dc)), machine (std::move (mn)), + auxiliary_machines (std::move (ams)), target (std::move (tg)), environment (std::move (en)), + auxiliary_environment (std::move (ae)), target_config (std::move (tc)), package_config (std::move (pc)), host (std::move (ht)), diff --git a/tests/manifest/machine-header.testscript b/tests/manifest/machine-header.testscript index 84295d2..559a107 100644 --- a/tests/manifest/machine-header.testscript +++ b/tests/manifest/machine-header.testscript @@ -13,6 +13,8 @@ test.options += -m id: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 name: windows_10-msvc_14 summary: Windows 10 build 1607 with VC 14 update 3 + role: build + ram-minimum: 4194304 EOF } @@ -52,6 +54,22 @@ EOI summary: Windows summary: Windows EOI + + : ram-maximum + : + $* <'stdin:3:1: error: machine maximum RAM redefinition' == 1 + : 1 + ram-maximum: 4194304 + ram-maximum: 4194304 + EOI + + : role + : + $* <'stdin:3:1: error: machine role redefinition' == 1 + : 1 + role: build + role: auxiliary + EOI } : empty diff --git a/tests/manifest/task-request.testscript b/tests/manifest/task-request.testscript index 85801a9..79f3982 100644 --- a/tests/manifest/task-request.testscript +++ b/tests/manifest/task-request.testscript @@ -18,6 +18,7 @@ test.options += -tq interactive-mode: both interactive-login: 10.5.0.1:5901 fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e + auxiliary-ram: 41943040 : id: a2b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 name: windows_10-msvc_14 @@ -72,6 +73,14 @@ test.options += -tq fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e fingerprint: 1105fb394ee870adb154b7abfbbae5755df7dcef6c81db34e8d1b68d2653734e EOI + + : auxiliary-ram + : + $* <'stdin:3:1: error: auxiliary machines RAM limit redefinition' == 1 + : 1 + auxiliary-ram: 41943040 + auxiliary-ram: 41943040 + EOI } : empty @@ -90,6 +99,13 @@ test.options += -tq : 1 toolchain-name: EOI + + : auxiliary-ram + : + $* <'stdin:2:15: error: auxiliary machines RAM limit should be 64-bit unsigned integer' == 1 + : 1 + auxiliary-ram: + EOI } : invalid-toolchain-version diff --git a/tests/manifest/task.testscript b/tests/manifest/task.testscript index d224124..8320f59 100644 --- a/tests/manifest/task.testscript +++ b/tests/manifest/task.testscript @@ -22,8 +22,14 @@ test.options += -t examples: foo-examples dependency-checksum: 12345 machine: windows_10-msvc_14 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_16 + auxiliary-machine: x86_64-linux_debian_12-mysql* target: x86_64-microsoft-win32-msvc14.0 environment: lld + auxiliary-environment:\ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ target-config: config.cc.coptions=/Z7 config.cc.loptions=/DEBUG package-config: config.foo.network=true warning-regex: '^warning: ' '^.+: warning: ' @@ -248,6 +254,14 @@ test.options += -t machine: windows_10-msvc_14 EOI + : auxiliary-machine + : + $* <'stdin:3:1: error: task auxiliary machine environment redefinition' == 1 + : 1 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_16 + auxiliary-machine-pgsql: x86_64-linux_debian_12-postgresql_14 + EOI + : target : $* <'stdin:3:1: error: task target redefinition' == 1 @@ -256,6 +270,22 @@ test.options += -t target: x86_64-microsoft-win32-msvc14.0 EOI + : auxiliary-environment + : + $* <'stdin:7:1: error: task auxiliary environment redefinition' == 1 + : 1 + auxiliary-environment: + \ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ + auxiliary-environment: + \ + PGSQL_DATABASE_HOST=192.168.0.1 + PGSQL_DATABASE_PORT=1245 + \ + EOI + : config : $* <'stdin:3:1: error: task target configuration redefinition' == 1 -- cgit v1.1