From adfdcc4b960377224f668c9853f142f19d25f466 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 23 Dec 2019 18:15:49 +0100 Subject: [PATCH] dnsdist: Allow retrieving and deleting a backend via its UUID Backends have a UUID since the introduction of the consistent hashing load-balancing policy, but until now it was not possible to retrieve or delete a backend via its UUID. --- pdns/dnsdist-console.cc | 4 +-- pdns/dnsdist-lua-bindings.cc | 1 + pdns/dnsdist-lua.cc | 39 ++++++++++++++++++---- pdns/dnsdistdist/docs/reference/config.rst | 11 ++++-- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index c6a9b8132a..c30030b84b 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -402,7 +402,7 @@ const std::vector g_consoleKeywords{ { "getQueryCounters", true, "[max=10]", "show current buffer of query counters, limited by 'max' if provided" }, { "getResponseRing", true, "", "return the current content of the response ring" }, { "getRespRing", true, "", "return the qname/rcode content of the response ring" }, - { "getServer", true, "n", "returns server with index n" }, + { "getServer", true, "id", "returns server with index 'n' or whose uuid matches if 'id' is an UUID string" }, { "getServers", true, "", "returns a table with all defined servers" }, { "getStatisticsCounters", true, "", "returns a map of statistic counters" }, { "getTLSContext", true, "n", "returns the TLS context with index n" }, @@ -487,7 +487,7 @@ const std::vector g_consoleKeywords{ { "rmResponseRule", true, "id", "remove response rule in position 'id', or whose uuid matches if 'id' is an UUID string" }, { "rmRule", true, "id", "remove rule in position 'id', or whose uuid matches if 'id' is an UUID string" }, { "rmSelfAnsweredResponseRule", true, "id", "remove self-answered response rule in position 'id', or whose uuid matches if 'id' is an UUID string" }, - { "rmServer", true, "n", "remove server with index n" }, + { "rmServer", true, "id", "remove server with index 'id' or whose uuid matches if 'id' is an UUID string" }, { "roundrobin", false, "", "Simple round robin over available servers" }, { "sendCustomTrap", true, "str", "send a custom `SNMP` trap from Lua, containing the `str` string"}, { "setACL", true, "{netmask, netmask}", "replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us" }, diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index 6a01adf1fc..b02b4232f9 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -118,6 +118,7 @@ void setupLuaBindings(bool client) ); g_lua.registerMember("order", &DownstreamState::order); g_lua.registerMember("name", &DownstreamState::name); + g_lua.registerFunction("getID", [](const DownstreamState& s) { return boost::uuids::to_string(s.id); }); /* dnsheader */ g_lua.registerFunction("setRD", [](dnsheader& dh, bool v) { diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 366376ef4d..b51fd65125 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -497,19 +497,29 @@ void setupLuaConfig(bool client) } ); g_lua.writeFunction("rmServer", - [](boost::variant, int> var) + [](boost::variant, int, std::string> var) { setLuaSideEffect(); - shared_ptr server; - auto* rem = boost::get>(&var); + shared_ptr server = nullptr; auto states = g_dstates.getCopy(); - if(rem) { + if (auto* rem = boost::get>(&var)) { server = *rem; } + else if (auto str = boost::get(&var)) { + const auto uuid = getUniqueID(*str); + for (auto& state : states) { + if (state->id == uuid) { + server = state; + } + } + } else { int idx = boost::get(var); server = states.at(idx); } + if (!server) { + throw std::runtime_error("unable to locate the requested server"); + } auto localPools = g_pools.getCopy(); for (const string& poolName : server->pools) { removeServerFromPool(localPools, poolName, server); @@ -725,10 +735,25 @@ void setupLuaConfig(bool client) return getDownstreamCandidates(g_pools.getCopy(), pool); }); - g_lua.writeFunction("getServer", [client](int i) { - if (client) + g_lua.writeFunction("getServer", [client](boost::variant i) { + if (client) { return std::make_shared(ComboAddress()); - return g_dstates.getCopy().at(i); + } + auto states = g_dstates.getCopy(); + if (auto str = boost::get(&i)) { + const auto uuid = getUniqueID(*str); + for (auto& state : states) { + if (state->id == uuid) { + return state; + } + } + } + else if (auto pos = boost::get(&i)) { + return states.at(*pos); + } + + g_outputBuffer = "Error: no rule matched\n"; + return std::shared_ptr(nullptr); }); g_lua.writeFunction("carbonServer", [](const std::string& address, boost::optional ourName, diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 7d40c1b552..14a56106e4 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -428,9 +428,12 @@ Servers .. function:: getServer(index) -> Server + .. versionchanged:: 1.5.0 + ``index`` might be an UUID. + Get a :class:`Server` - :param int index: The number of the server (as seen in :func:`showServers`). + :param int or str index: The number of the server (as seen in :func:`showServers`) or its UUID as a string. :returns: The :class:`Server` object or nil .. function:: getServers() @@ -438,11 +441,15 @@ Servers Returns a table with all defined servers. .. function:: rmServer(index) + rmServer(uuid) rmServer(server) + .. versionchanged:: 1.5.0 + ``uuid`` selection added. + Remove a backend server. - :param int index: The number of the server (as seen in :func:`showServers`). + :param int or str index: The number of the server (as seen in :func:`showServers`), its UUID as a string, or a server object. :param Server server: A :class:`Server` object as returned by e.g. :func:`getServer`. Server Functions -- 2.47.2