From 643a7419b4a565a248ad65ab55df06780ca5bea3 Mon Sep 17 00:00:00 2001 From: Nitzan Mordechai Date: Tue, 23 Jun 2026 10:23:54 +0000 Subject: [PATCH] mon/config: trim whitespace in config target When set\get\rm config values with leading or trailing spaces, those spaces need to be removed before we are trying to get\set\rm those keys. add trim code before each approch and also for exist keys in config. Fixes: https://tracker.ceph.com/issues/77598 Signed-off-by: Nitzan Mordechai (cherry picked from commit cab98604fadb8bdc30d27188c44b313e12568d97) --- qa/workunits/mon/config.sh | 17 +++++++++ src/mon/ConfigMap.cc | 2 ++ src/mon/ConfigMonitor.cc | 2 ++ src/test/mon/test_config_map.cc | 61 +++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/qa/workunits/mon/config.sh b/qa/workunits/mon/config.sh index 10cbe5630e91..d6c2d850f41f 100755 --- a/qa/workunits/mon/config.sh +++ b/qa/workunits/mon/config.sh @@ -73,6 +73,23 @@ ceph config rm client.foo debug_asok ceph config set client.foo debug_asok 66 ceph config rm client.foo 'debug asok' +# whitespace in who/section (e.g. "osd.0 " with stray trailing spaces) +ceph config set 'osd.0 ' debug_asok 44 +ceph config get osd.0 debug_asok | grep 44 +while ! ceph tell osd.0 config get debug_asok | grep 44 +do + sleep 1 +done +ceph config rm osd.0 debug_asok +while ceph tell osd.0 config get debug_asok | grep 44 +do + sleep 1 +done + +ceph config set ' osd.0' debug_asok 55 +ceph config get osd.0 debug_asok | grep 55 +ceph config rm osd.0 debug_asok + # help ceph config help debug_asok | grep debug_asok diff --git a/src/mon/ConfigMap.cc b/src/mon/ConfigMap.cc index bfd837727d18..45111a21562a 100644 --- a/src/mon/ConfigMap.cc +++ b/src/mon/ConfigMap.cc @@ -6,6 +6,7 @@ #include "common/entity_name.h" #include +#include #define dout_subsys ceph_subsys_mon #undef dout_prefix @@ -207,6 +208,7 @@ bool ConfigMap::parse_mask( boost::split(split, who, [](char c){ return c == '/'; }); for (unsigned j = 0; j < split.size(); ++j) { auto& i = split[j]; + boost::algorithm::trim(i); if (i == "global") { *section = "global"; continue; diff --git a/src/mon/ConfigMonitor.cc b/src/mon/ConfigMonitor.cc index e377008240e6..62f38cd96bd6 100644 --- a/src/mon/ConfigMonitor.cc +++ b/src/mon/ConfigMonitor.cc @@ -19,6 +19,7 @@ #include "crush/CrushWrapper.h" #include +#include #define dout_subsys ceph_subsys_mon #undef dout_prefix @@ -296,6 +297,7 @@ bool ConfigMonitor::preprocess_command(MonOpRequestRef op) } else if (prefix == "config get") { string who, name; cmd_getval(cmdmap, "who", who); + boost::algorithm::trim(who); EntityName entity; if (!entity.from_str(who) && diff --git a/src/test/mon/test_config_map.cc b/src/test/mon/test_config_map.cc index eef42de6bd1c..f5ab05cc216c 100644 --- a/src/test/mon/test_config_map.cc +++ b/src/test/mon/test_config_map.cc @@ -53,6 +53,67 @@ TEST(ConfigMap, parse_key) } } +TEST(ConfigMap, parse_mask) +{ + { + std::string section; + OptionMask mask; + ASSERT_TRUE(ConfigMap::parse_mask("osd.2", §ion, &mask)); + ASSERT_EQ("osd.2", section); + } + { + std::string section; + OptionMask mask; + ASSERT_TRUE(ConfigMap::parse_mask("osd.2 ", §ion, &mask)); + ASSERT_EQ("osd.2", section); + } + { + std::string section; + OptionMask mask; + ASSERT_TRUE(ConfigMap::parse_mask(" osd.2", §ion, &mask)); + ASSERT_EQ("osd.2", section); + } + { + std::string section; + OptionMask mask; + ASSERT_TRUE(ConfigMap::parse_mask(" global ", §ion, &mask)); + ASSERT_EQ("global", section); + } +} + +TEST(ConfigMap, add_option_who_whitespace) +{ + ConfigMap cm; + boost::intrusive_ptr cct{new CephContext(CEPH_ENTITY_TYPE_CLIENT), false}; + auto crush = std::make_unique(); + crush->finalize(); + + int r = cm.add_option( + cct.get(), "debug_ms", "osd.2 ", "1/1", + [&](const std::string& name) { + return nullptr; + }); + ASSERT_EQ(0, r); + ASSERT_EQ(1, cm.by_id.size()); + ASSERT_EQ(1, cm.by_id["osd.2"].options.size()); + + EntityName n; + n.set(CEPH_ENTITY_TYPE_OSD, "2"); + auto c = cm.generate_entity_map(n, {}, crush.get(), "none", nullptr); + ASSERT_EQ(1, c.size()); + ASSERT_EQ("1/1", c["debug_ms"]); + + r = cm.add_option( + cct.get(), "foo", "osd.2", "clean", + [&](const std::string& name) { + return nullptr; + }); + ASSERT_EQ(0, r); + + ASSERT_EQ(1, cm.by_id.size()); + ASSERT_EQ(2, cm.by_id["osd.2"].options.size()); +} + TEST(ConfigMap, add_option) { ConfigMap cm; -- 2.47.3