Skip to content

Commit

Permalink
utility: convert typed_config to factory config (#10418)
Browse files Browse the repository at this point in the history
Convert typed_config to factory config

Risk Level: Low
Testing: Unit test

Signed-off-by: Yan Xue <yxyan@google.com>
  • Loading branch information
yxue authored Mar 18, 2020
1 parent c34b82f commit 8704403
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
25 changes: 24 additions & 1 deletion source/common/config/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ class Utility {

/**
* Translate a nested config into a proto message provided by the implementation factory.
* @param extension_name name of extension corresponding to config.
* @param enclosing_message proto that contains a field 'config'. Note: the enclosing proto is
* provided because for statically registered implementations, a custom config is generally
* optional, which means the conversion must be done conditionally.
Expand All @@ -269,6 +268,30 @@ class Utility {
return config;
}

/**
* Translate the typed any field into a proto message provided by the implementation factory.
* @param typed_config typed configuration.
* @param validation_visitor message validation visitor instance.
* @param factory implementation factory with the method 'createEmptyConfigProto' to produce a
* proto to be filled with the translated configuration.
*/
template <class Factory>
static ProtobufTypes::MessagePtr
translateAnyToFactoryConfig(const ProtobufWkt::Any& typed_config,
ProtobufMessage::ValidationVisitor& validation_visitor,
Factory& factory) {
ProtobufTypes::MessagePtr config = factory.createEmptyConfigProto();

// Fail in an obvious way if a plugin does not return a proto.
RELEASE_ASSERT(config != nullptr, "");

// Check that the config type is not google.protobuf.Empty
RELEASE_ASSERT(config->GetDescriptor()->full_name() != "google.protobuf.Empty", "");

translateOpaqueConfig(typed_config, ProtobufWkt::Struct(), validation_visitor, *config);
return config;
}

/**
* Truncates the message to a length less than default GRPC trailers size limit (by default 8KiB).
*/
Expand Down
36 changes: 36 additions & 0 deletions test/common/config/utility_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "common/config/well_known_names.h"
#include "common/protobuf/protobuf.h"

#include "test/mocks/config/mocks.h"
#include "test/mocks/grpc/mocks.h"
#include "test/mocks/local_info/mocks.h"
#include "test/mocks/stats/mocks.h"
Expand Down Expand Up @@ -287,6 +288,41 @@ TEST(UtilityTest, AnyWrongType) {
R"(Unable to unpack as google.protobuf.Timestamp: \[type.googleapis.com/google.protobuf.Duration\] .*)");
}

TEST(UtilityTest, TranslateAnyWrongToFactoryConfig) {
ProtobufWkt::Duration source_duration;
source_duration.set_seconds(42);
ProtobufWkt::Any typed_config;
typed_config.PackFrom(source_duration);

MockTypedFactory factory;
EXPECT_CALL(factory, createEmptyConfigProto()).WillOnce(Invoke([]() -> ProtobufTypes::MessagePtr {
return ProtobufTypes::MessagePtr{new ProtobufWkt::Timestamp()};
}));

EXPECT_THROW_WITH_REGEX(
Utility::translateAnyToFactoryConfig(typed_config,
ProtobufMessage::getStrictValidationVisitor(), factory),
EnvoyException,
R"(Unable to unpack as google.protobuf.Timestamp: \[type.googleapis.com/google.protobuf.Duration\] .*)");
}

TEST(UtilityTest, TranslateAnyToFactoryConfig) {
ProtobufWkt::Duration source_duration;
source_duration.set_seconds(42);
ProtobufWkt::Any typed_config;
typed_config.PackFrom(source_duration);

MockTypedFactory factory;
EXPECT_CALL(factory, createEmptyConfigProto()).WillOnce(Invoke([]() -> ProtobufTypes::MessagePtr {
return ProtobufTypes::MessagePtr{new ProtobufWkt::Duration()};
}));

auto config = Utility::translateAnyToFactoryConfig(
typed_config, ProtobufMessage::getStrictValidationVisitor(), factory);

EXPECT_THAT(*config, ProtoEq(source_duration));
}

void packTypedStructIntoAny(ProtobufWkt::Any& typed_config, const Protobuf::Message& inner) {
udpa::type::v1::TypedStruct typed_struct;
(*typed_struct.mutable_type_url()) =
Expand Down
1 change: 1 addition & 0 deletions test/mocks/config/mocks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ MockSubscriptionCallbacks::MockSubscriptionCallbacks() {

MockSubscriptionCallbacks::~MockSubscriptionCallbacks() = default;

MockTypedFactory::~MockTypedFactory() = default;
} // namespace Config
} // namespace Envoy
11 changes: 11 additions & 0 deletions test/mocks/config/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "envoy/config/endpoint/v3/endpoint.pb.h"
#include "envoy/config/grpc_mux.h"
#include "envoy/config/subscription.h"
#include "envoy/config/typed_config.h"
#include "envoy/service/discovery/v3/discovery.pb.h"

#include "common/config/config_provider_impl.h"
Expand Down Expand Up @@ -119,5 +120,15 @@ class MockConfigProviderManager : public ConfigProviderManager {
const Envoy::Config::ConfigProviderManager::OptionalArg& optarg));
};

class MockTypedFactory : public TypedFactory {
public:
~MockTypedFactory() override;

MOCK_METHOD(ProtobufTypes::MessagePtr, createEmptyConfigProto, ());
MOCK_METHOD(std::string, configType, ());
MOCK_METHOD(std::string, name, (), (const));
MOCK_METHOD(std::string, category, (), (const));
};

} // namespace Config
} // namespace Envoy

0 comments on commit 8704403

Please sign in to comment.