diff --git a/docs/configuration/cluster_manager/cluster.rst b/docs/configuration/cluster_manager/cluster.rst index cb78a199b917a..cc87ae27a1f7c 100644 --- a/docs/configuration/cluster_manager/cluster.rst +++ b/docs/configuration/cluster_manager/cluster.rst @@ -28,6 +28,7 @@ Cluster name *(required, string)* Supplies the name of the cluster which must be unique across all clusters. The cluster name is used when emitting :ref:`statistics `. + The cluster name can be at most 60 characters long, and must **not** contain ``:``. type *(required, string)* The :ref:`service discovery type ` to diff --git a/source/common/json/config_schemas.cc b/source/common/json/config_schemas.cc index d7d6c693f326d..f3fb93b6530f8 100644 --- a/source/common/json/config_schemas.cc +++ b/source/common/json/config_schemas.cc @@ -1032,7 +1032,12 @@ const std::string Json::Schema::CLUSTER_SCHEMA(R"EOF( }, "type" : "object", "properties" : { - "name" : {"type" : "string"}, + "name" : { + "type" : "string", + "pattern" : "^[^:]+$", + "minLength" : 1, + "maxLength" : 60 + }, "type" : { "type" : "string", "enum" : ["static", "strict_dns", "logical_dns", "sds"] diff --git a/test/common/upstream/cluster_manager_impl_test.cc b/test/common/upstream/cluster_manager_impl_test.cc index 584e15aa48a93..8a9787d58d429 100644 --- a/test/common/upstream/cluster_manager_impl_test.cc +++ b/test/common/upstream/cluster_manager_impl_test.cc @@ -260,6 +260,40 @@ TEST_F(ClusterManagerImplTest, UnknownHcType) { EXPECT_THROW(create(*loader), EnvoyException); } +TEST_F(ClusterManagerImplTest, MaxClusterName) { + std::string json = R"EOF( + { + "clusters": [ + { + "name": "clusterwithareallyreallylongnamemorethanmaxcharsallowedbyschema" + }] + } + )EOF"; + + Json::ObjectPtr loader = Json::Factory::LoadFromString(json); + EXPECT_THROW_WITH_MESSAGE(create(*loader), Json::Exception, + "JSON object doesn't conform to schema.\n Invalid schema: " + "#/properties/name.\n Invalid keyword: maxLength.\n Invalid document " + "key: #/name"); +} + +TEST_F(ClusterManagerImplTest, InvalidClusterNameChars) { + std::string json = R"EOF( + { + "clusters": [ + { + "name": "cluster:" + }] + } + )EOF"; + + Json::ObjectPtr loader = Json::Factory::LoadFromString(json); + EXPECT_THROW_WITH_MESSAGE(create(*loader), Json::Exception, + "JSON object doesn't conform to schema.\n Invalid schema: " + "#/properties/name.\n Invalid keyword: pattern.\n Invalid document " + "key: #/name"); +} + TEST_F(ClusterManagerImplTest, TcpHealthChecker) { std::string json = R"EOF( { diff --git a/test/test_common/utility.h b/test/test_common/utility.h index 2e5bd9e3d16af..2376cfe8a6e31 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -5,6 +5,14 @@ #include "common/http/header_map_impl.h" +#define EXPECT_THROW_WITH_MESSAGE(statement, expected_exception, message) \ + try { \ + statement; \ + ADD_FAILURE() << "Exception should take place. It did not."; \ + } catch (expected_exception & e) { \ + EXPECT_EQ(message, std::string(e.what())); \ + } + class TestUtility { public: /**