diff --git a/changelogs/current.yaml b/changelogs/current.yaml index d46e53b6071e..d199a25651a2 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -128,6 +128,11 @@ bug_fixes: the number of requests per I/O cycle is configured and an HTTP decoder filter that pauses filter chain is present. This behavior can be reverted by setting the runtime guard ``envoy.reloadable_features.use_filter_manager_state_for_downstream_end_stream`` to false. +- area: runtime + change: | + Fixed an inconsistency in how boolean values are loaded in RTDS, where they were previously converted to "1"/"0" + instead of "true"/"false". The correct string representation ("true"/"false") will now be used. This change can be + reverted by setting the runtime guard ``envoy.reloadable_features.boolean_to_string_fix`` to false. removed_config_or_runtime: # *Normally occurs at the end of the* :ref:`deprecation period ` diff --git a/source/common/runtime/runtime_features.cc b/source/common/runtime/runtime_features.cc index 1411ac47f991..860aaf353e56 100644 --- a/source/common/runtime/runtime_features.cc +++ b/source/common/runtime/runtime_features.cc @@ -30,6 +30,7 @@ // ASAP by filing a bug on github. Overriding non-buggy code is strongly discouraged to avoid the // problem of the bugs being found after the old code path has been removed. RUNTIME_GUARD(envoy_reloadable_features_allow_alt_svc_for_ips); +RUNTIME_GUARD(envoy_reloadable_features_boolean_to_string_fix); RUNTIME_GUARD(envoy_reloadable_features_check_switch_protocol_websocket_handshake); RUNTIME_GUARD(envoy_reloadable_features_conn_pool_delete_when_idle); RUNTIME_GUARD(envoy_reloadable_features_consistent_header_validation); diff --git a/source/common/runtime/runtime_impl.cc b/source/common/runtime/runtime_impl.cc index 917ef6e655a1..24b1f1ff04c2 100644 --- a/source/common/runtime/runtime_impl.cc +++ b/source/common/runtime/runtime_impl.cc @@ -375,7 +375,13 @@ SnapshotImpl::Entry SnapshotImpl::createEntry(const ProtobufWkt::Value& value, case ProtobufWkt::Value::kBoolValue: entry.bool_value_ = value.bool_value(); if (entry.raw_string_value_.empty()) { - entry.raw_string_value_ = absl::StrCat(value.bool_value()); + if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.boolean_to_string_fix")) { + // Convert boolean to "true"/"false" + entry.raw_string_value_ = value.bool_value() ? "true" : "false"; + } else { + // Use absl::StrCat for backward compatibility, which converts to "1"/"0" + entry.raw_string_value_ = absl::StrCat(value.bool_value()); + } } break; case ProtobufWkt::Value::kStructValue: diff --git a/test/common/runtime/runtime_impl_test.cc b/test/common/runtime/runtime_impl_test.cc index 37540ce90d29..16d1ea5a2ef7 100644 --- a/test/common/runtime/runtime_impl_test.cc +++ b/test/common/runtime/runtime_impl_test.cc @@ -32,6 +32,7 @@ #ifdef ENVOY_ENABLE_QUIC #include "quiche/common/platform/api/quiche_flags.h" #endif +ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_boolean_to_string_fix); ABSL_DECLARE_FLAG(bool, envoy_reloadable_features_reject_invalid_yaml); using testing::_; @@ -1314,6 +1315,40 @@ TEST_F(RtdsLoaderImplTest, BadConfigSource) { "bad config"); } +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagEnabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, true); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("true", loader_->snapshot().get("toggle").value().get()); +} + +TEST_F(RtdsLoaderImplTest, BooleanToStringConversionWhenFlagDisabled) { + setup(); + + absl::SetFlag(&FLAGS_envoy_reloadable_features_boolean_to_string_fix, false); + + auto runtime = TestUtility::parseYaml(R"EOF( + name: some_resource + layer: + toggle: true + )EOF"); + + EXPECT_CALL(rtds_init_callback_, Call()); + doOnConfigUpdateVerifyNoThrow(runtime); + + EXPECT_EQ("1", loader_->snapshot().get("toggle").value().get()); // Assuming previous behavior +} + } // namespace } // namespace Runtime } // namespace Envoy