From fdf783df6591552b01579c682d26581fe67dbc1b Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Wed, 11 Dec 2024 18:21:40 +0000 Subject: [PATCH] cluster/Backend: Handle unspecified table/set Same as what we do in Broker. Use the expected type if publishing a table() or set() parameter. This fixes issues when switching sumstats to Cluster::publish() --- src/cluster/Backend.cc | 8 +- .../..manager.out | 5 ++ .../..worker.out | 3 + .../cluster/generic/publish-unspecified.zeek | 90 +++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 testing/btest/Baseline/cluster.generic.publish-unspecified/..manager.out create mode 100644 testing/btest/Baseline/cluster.generic.publish-unspecified/..worker.out create mode 100644 testing/btest/cluster/generic/publish-unspecified.zeek diff --git a/src/cluster/Backend.cc b/src/cluster/Backend.cc index d1e6ef9a4f..feb4a1df77 100644 --- a/src/cluster/Backend.cc +++ b/src/cluster/Backend.cc @@ -36,9 +36,15 @@ std::optional detail::check_args(const zeek::FuncValPtr& handler, ze for ( size_t i = 0; i < args.size(); i++ ) { const auto& a = args[i]; - const auto& got_type = a->GetType(); + auto got_type = a->GetType(); const auto& expected_type = types[i]; + // If called with an unspecified table or set, adopt the expected type + // as otherwise same_type() fails. + if ( got_type->Tag() == TYPE_TABLE && got_type->AsTableType()->IsUnspecifiedTable() ) + if ( expected_type->Tag() == TYPE_TABLE && got_type->IsSet() == expected_type->IsSet() ) + got_type = expected_type; + if ( ! same_type(got_type, expected_type) ) { zeek::reporter->Error("event parameter #%zu type mismatch, got %s, expecting %s", i + 1, zeek::obj_desc_short(got_type.get()).c_str(), diff --git a/testing/btest/Baseline/cluster.generic.publish-unspecified/..manager.out b/testing/btest/Baseline/cluster.generic.publish-unspecified/..manager.out new file mode 100644 index 0000000000..41549e7f39 --- /dev/null +++ b/testing/btest/Baseline/cluster.generic.publish-unspecified/..manager.out @@ -0,0 +1,5 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +node_up, worker-1 +pong_table, hello, ResultTable, {\x0a\x0a} +pong_set, hello, ResultSet, {\x0a\x0a} +node_down, worker-1 diff --git a/testing/btest/Baseline/cluster.generic.publish-unspecified/..worker.out b/testing/btest/Baseline/cluster.generic.publish-unspecified/..worker.out new file mode 100644 index 0000000000..161db98503 --- /dev/null +++ b/testing/btest/Baseline/cluster.generic.publish-unspecified/..worker.out @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ping_table, hello, ResultTable, {\x0a\x0a} +ping_set, hello, ResultSet, {\x0a\x0a} diff --git a/testing/btest/cluster/generic/publish-unspecified.zeek b/testing/btest/cluster/generic/publish-unspecified.zeek new file mode 100644 index 0000000000..a41a444d36 --- /dev/null +++ b/testing/btest/cluster/generic/publish-unspecified.zeek @@ -0,0 +1,90 @@ +# @TEST-DOC: Startup a manager running the ZeroMQ proxy thread, a worker connects and the manager sends a finish event to terminate the worker. +# +# @TEST-REQUIRES: have-zeromq +# +# @TEST-GROUP: cluster-zeromq +# +# @TEST-PORT: XPUB_PORT +# @TEST-PORT: XSUB_PORT +# @TEST-PORT: LOG_PULL_PORT +# +# @TEST-EXEC: cp $FILES/zeromq/cluster-layout-simple.zeek cluster-layout.zeek +# @TEST-EXEC: cp $FILES/zeromq/test-bootstrap.zeek zeromq-test-bootstrap.zeek +# +# @TEST-EXEC: zeek --parse-only manager.zeek worker.zeek +# +# @TEST-EXEC: btest-bg-run manager "ZEEKPATH=$ZEEKPATH:.. && CLUSTER_NODE=manager zeek -b ../manager.zeek >out" +# @TEST-EXEC: btest-bg-run worker "ZEEKPATH=$ZEEKPATH:.. && CLUSTER_NODE=worker-1 zeek -b ../worker.zeek >out" +# +# @TEST-EXEC: btest-bg-wait 30 +# @TEST-EXEC: btest-diff ./manager/out +# @TEST-EXEC: btest-diff ./worker/out + + +# @TEST-START-FILE common.zeek +@load ./zeromq-test-bootstrap + +type ResultTable: table[string] of count; +type ResultSet : set[count]; + +global ping_table: event(msg: string, t: ResultTable) &is_used; +global pong_table: event(msg: string, t: ResultTable) &is_used; + +global ping_set: event(msg: string, s: ResultSet) &is_used; +global pong_set: event(msg: string, s: ResultSet) &is_used; + +global finish: event() &is_used; +# @TEST-END-FILE + +# @TEST-START-FILE manager.zeek +@load ./common.zeek +# If a node comes up that isn't us, send it a finish event. +event Cluster::node_up(name: string, id: string) + { + print "node_up", name; + Cluster::publish(Cluster::nodeid_topic(id), ping_table, "hello", table()); + Cluster::publish(Cluster::nodeid_topic(id), ping_set, "hello", set()); + } + + +event pong_table(msg: string, t: ResultTable) + { + print "pong_table", msg, type_name(t), cat(t); + } + +event pong_set(msg: string, t: ResultSet) + { + print "pong_set", msg, type_name(t), cat(t); + Cluster::publish(Cluster::worker_topic, finish); + } + +# If the worker vanishes, finish the test. +event Cluster::node_down(name: string, id: string) + { + print "node_down", name; + terminate(); + } +# @TEST-END-FILE + +# @TEST-START-FILE worker.zeek +@load ./common.zeek + +event ping_table(msg: string, t: ResultTable) &is_used + { + print "ping_table", msg, type_name(t), cat(t); + local e = Cluster::make_event(pong_table, msg, table()); + Cluster::publish(Cluster::manager_topic, e); + } + +event ping_set(msg: string, t: ResultSet) &is_used + { + print "ping_set", msg, type_name(t), cat(t); + local e = Cluster::make_event(pong_set, msg, set()); + Cluster::publish(Cluster::manager_topic, e); + } + +event finish() + { + terminate(); + } +# @TEST-END-FILE