diff --git a/scripts/base/frameworks/supervisor/api.zeek b/scripts/base/frameworks/supervisor/api.zeek index da3ddde0e3..cc9f3fb004 100644 --- a/scripts/base/frameworks/supervisor/api.zeek +++ b/scripts/base/frameworks/supervisor/api.zeek @@ -45,8 +45,15 @@ export { ## Whether to start the node in bare mode. When left out, the node ## inherits the bare-mode status the supervisor itself runs with. bare_mode: bool &optional; - ## Additional script filenames/paths that the node should load. - scripts: vector of string &default = vector(); + ## Additional script filenames/paths that the node should load + ## after the base scripts, and prior to any user-specified ones. + addl_base_scripts: vector of string &default = vector(); + ## Additional script filenames/paths that the node should load + ## after any user-specified scripts. + addl_user_scripts: vector of string &default = vector(); + ## The former name of addl_user_scripts. + scripts: vector of string &default = vector() + &deprecated="Remove in 6.1. Use the addl_user_scripts field instead."; ## Environment variables to define in the supervised node. env: table[string] of string &default=table(); ## A cpu/core number to which the node will try to pin itself. diff --git a/src/supervisor/Supervisor.cc b/src/supervisor/Supervisor.cc index 032d19b44b..67f1e7be1f 100644 --- a/src/supervisor/Supervisor.cc +++ b/src/supervisor/Supervisor.cc @@ -1256,6 +1256,22 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node) if ( bare_mode_val ) rval.bare_mode = bare_mode_val->AsBool(); + auto addl_base_scripts_val = node->GetField("addl_base_scripts")->AsVectorVal(); + + for ( auto i = 0u; i < addl_base_scripts_val->Size(); ++i ) + { + auto script = addl_base_scripts_val->StringValAt(i)->ToStdString(); + rval.addl_base_scripts.emplace_back(std::move(script)); + } + + auto addl_user_scripts_val = node->GetField("addl_user_scripts")->AsVectorVal(); + + for ( auto i = 0u; i < addl_user_scripts_val->Size(); ++i ) + { + auto script = addl_user_scripts_val->StringValAt(i)->ToStdString(); + rval.addl_user_scripts.emplace_back(std::move(script)); + } + auto scripts_val = node->GetField("scripts")->AsVectorVal(); for ( auto i = 0u; i < scripts_val->Size(); ++i ) @@ -1332,6 +1348,16 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromJSON(std::string_view json) if ( auto it = j.FindMember("bare_mode"); it != j.MemberEnd() ) rval.bare_mode = it->value.GetBool(); + auto& addl_base_scripts = j["addl_base_scripts"]; + + for ( auto it = addl_base_scripts.Begin(); it != addl_base_scripts.End(); ++it ) + rval.addl_base_scripts.emplace_back(it->GetString()); + + auto& addl_user_scripts = j["addl_user_scripts"]; + + for ( auto it = addl_user_scripts.Begin(); it != addl_user_scripts.End(); ++it ) + rval.addl_user_scripts.emplace_back(it->GetString()); + auto& scripts = j["scripts"]; for ( auto it = scripts.Begin(); it != scripts.End(); ++it ) @@ -1396,6 +1422,22 @@ RecordValPtr Supervisor::NodeConfig::ToRecord() const if ( bare_mode ) rval->AssignField("bare_mode", *bare_mode); + auto abs_t = rt->GetFieldType("addl_base_scripts"); + auto addl_base_scripts_val = make_intrusive(std::move(abs_t)); + + for ( const auto& s : addl_base_scripts ) + addl_base_scripts_val->Assign(addl_base_scripts_val->Size(), make_intrusive(s)); + + rval->AssignField("addl_base_scripts", std::move(addl_base_scripts_val)); + + auto aus_t = rt->GetFieldType("addl_user_scripts"); + auto addl_user_scripts_val = make_intrusive(std::move(aus_t)); + + for ( const auto& s : addl_user_scripts ) + addl_user_scripts_val->Assign(addl_user_scripts_val->Size(), make_intrusive(s)); + + rval->AssignField("addl_user_scripts", std::move(addl_user_scripts_val)); + auto st = rt->GetFieldType("scripts"); auto scripts_val = make_intrusive(std::move(st)); @@ -1601,8 +1643,11 @@ void SupervisedNode::Init(Options* options) const if ( config.interface ) options->interface = *config.interface; - for ( const auto& s : config.scripts ) - options->scripts_to_load.emplace_back(s); + auto& stl = options->scripts_to_load; + + stl.insert(stl.begin(), config.addl_base_scripts.begin(), config.addl_base_scripts.end()); + stl.insert(stl.end(), config.addl_user_scripts.begin(), config.addl_user_scripts.end()); + stl.insert(stl.end(), config.scripts.begin(), config.scripts.end()); } RecordValPtr Supervisor::Status(std::string_view node_name) diff --git a/src/supervisor/Supervisor.h b/src/supervisor/Supervisor.h index ec3e08bb2b..449eb104a2 100644 --- a/src/supervisor/Supervisor.h +++ b/src/supervisor/Supervisor.h @@ -198,9 +198,20 @@ public: */ std::optional bare_mode; /** - * Additional script filename/paths that the node should load. + * Additional script filenames/paths that the node should load + * after the base scripts, and prior to any user-specified ones. */ - std::vector scripts; + std::vector addl_base_scripts; + /** + * Additional script filename/paths that the node should load + * after any user-specified scripts. + */ + std::vector addl_user_scripts; + /** + * The former name for addl_user_scripts, now deprecated. + */ + std::vector scripts + [[deprecated("Remove in v6.1. Use NodeConfig::addl_user_scripts.")]]; /** * Environment variables and values to define in the node. */ diff --git a/testing/btest/Baseline/supervisor.config-scripts/zeek.node.out b/testing/btest/Baseline/supervisor.config-scripts/zeek.node.out index fdd7cdf788..cb24a6aeff 100644 --- a/testing/btest/Baseline/supervisor.config-scripts/zeek.node.out +++ b/testing/btest/Baseline/supervisor.config-scripts/zeek.node.out @@ -1,4 +1,5 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -supervised node zeek_init() -supervised node loaded qux.zeek +supervised node zeek_init(), counter at 1 +supervised node loaded addl_user_script.zeek, counter at 2 +supervised node loaded script.zeek, counter at 3 supervised node zeek_done() diff --git a/testing/btest/supervisor/config-scripts.zeek b/testing/btest/supervisor/config-scripts.zeek index e29a59d0eb..d48281b9a4 100644 --- a/testing/btest/supervisor/config-scripts.zeek +++ b/testing/btest/supervisor/config-scripts.zeek @@ -26,7 +26,9 @@ event zeek_init() supervisor_output_file = open("supervisor.out"); print supervisor_output_file, "supervisor zeek_init()"; local sn = Supervisor::NodeConfig($name="grault", - $scripts=vector("../qux.zeek")); + $addl_base_scripts=vector("../addl_base_script.zeek"), + $addl_user_scripts=vector("../addl_user_script.zeek"), + $scripts=vector("../script.zeek")); local res = Supervisor::create(sn); if ( res != "" ) @@ -36,7 +38,15 @@ event zeek_init() { Broker::peer("127.0.0.1", to_port(getenv("BROKER_PORT"))); node_output_file = open("node.out"); - print node_output_file, "supervised node zeek_init()"; + +@ifdef ( Pre::counter ) + # Even though this else-block runs only in the supervised node, + # it still needs to parse correctly in the Supervisor, so we + # need to condition this with availability of the counter (which + # only exists in the supervised node). + ++Pre::counter; + print node_output_file, fmt("supervised node zeek_init(), counter at %s", Pre::counter); +@endif } } @@ -60,11 +70,32 @@ event zeek_done() print supervisor_output_file, "supervisor zeek_done()"; } -@TEST-START-FILE qux.zeek +@TEST-START-FILE addl_base_script.zeek + +module Pre; + +export { + global counter = 0; +} + +@TEST-END-FILE + +@TEST-START-FILE addl_user_script.zeek event zeek_init() &priority=-10 { - print node_output_file, "supervised node loaded qux.zeek"; + ++Pre::counter; + print node_output_file, fmt("supervised node loaded addl_user_script.zeek, counter at %s", Pre::counter); + } + +@TEST-END-FILE + +@TEST-START-FILE script.zeek + +event zeek_init() &priority=-20 + { + ++Pre::counter; + print node_output_file, fmt("supervised node loaded script.zeek, counter at %s", Pre::counter); } @TEST-END-FILE