Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions google/cloud/storage/grpc_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ struct GrpcMetricsExcludedLabelsOption {
using Type = std::set<std::string>;
};

/**
* Option to attempt DirectPath over Interconnect.
*
* When this option is enabled, the client bypasses GCE VM environment/BIOS
* checks and configures the gRPC channel to target
* `google-c2p:///storage-direct.googleapis.com?force-xds` with standard TLS.
*/
struct DirectPathXdsOverInterconnectOption {
using Type = bool;
};

GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace storage_experimental
} // namespace cloud
Expand Down
34 changes: 27 additions & 7 deletions google/cloud/storage/internal/grpc/default_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,33 @@ Options DefaultOptionsGrpc(
auto const ep = google::cloud::internal::UniverseDomainEndpoint(
"storage.googleapis.com", options);

// Set default to direct connectivity if we can detect we are running in GCP
// and there is not already a set endpoint or unviverse domain endpoint.
if ((!options.has<EndpointOption>() &&
!options.has<internal::UniverseDomainOption>()) &&
(gcp_detector->IsGoogleCloudBios() ||
gcp_detector->IsGoogleCloudServerless())) {
options.set<EndpointOption>("google-c2p:///storage.googleapis.com");
if (!options
.has<storage_experimental::DirectPathXdsOverInterconnectOption>()) {
auto const env =
GetEnv("GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT");
if (env.has_value() && *env == "true") {
options.set<storage_experimental::DirectPathXdsOverInterconnectOption>(
true);
}
}
bool const direct_path_interconnect =
options.get<storage_experimental::DirectPathXdsOverInterconnectOption>();

// Set default to direct connectivity if DirectPath over Interconnect is
// enabled, or if running in GCP and no endpoint or universe domain is
// explicitly configured.
if (!options.has<EndpointOption>() &&
!options.has<internal::UniverseDomainOption>()) {
if (direct_path_interconnect) {
options.set<EndpointOption>(
"google-c2p:///storage-direct.googleapis.com?force-xds");
if (!options.has<AuthorityOption>()) {
options.set<AuthorityOption>("storage.googleapis.com");
}
} else if (gcp_detector->IsGoogleCloudBios() ||
gcp_detector->IsGoogleCloudServerless()) {
options.set<EndpointOption>("google-c2p:///storage.googleapis.com");
}
}

options = google::cloud::internal::MergeOptions(
Expand Down
143 changes: 143 additions & 0 deletions google/cloud/storage/internal/grpc/default_options_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ TEST(DefaultOptionsGrpc, DefaultOptionsGrpcChannelCount) {
{"storage.googleapis.com", 4, std::numeric_limits<int>::max()},
{"google-c2p:///storage.googleapis.com", 1, 1},
{"google-c2p-experimental:///storage.googleapis.com", 1, 1},
{"google-c2p:///storage-direct.googleapis.com?force-xds", 1, 1},
};

for (auto const& test : cases) {
Expand Down Expand Up @@ -95,6 +96,148 @@ TEST(DefaultOptionsGrpc, DefaultEndpointsDirectPath) {
EXPECT_EQ(options.get<AuthorityOption>(), "storage.googleapis.com");
}

TEST(DefaultOptionsGrpc, DefaultEndpointsDirectPathOverInterconnectOption) {
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}.set<storage_experimental::DirectPathXdsOverInterconnectOption>(
true),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(),
"google-c2p:///storage-direct.googleapis.com?force-xds");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.googleapis.com");
EXPECT_EQ(options.get<GrpcNumChannelsOption>(), 1);
}

TEST(DefaultOptionsGrpc, DefaultEndpointsDirectPathOverInterconnectEnvVar) {
ScopedEnvironment env("GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT",
"true");
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(Options{}, mock_detector);
EXPECT_EQ(options.get<EndpointOption>(),
"google-c2p:///storage-direct.googleapis.com?force-xds");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.googleapis.com");
EXPECT_EQ(options.get<GrpcNumChannelsOption>(), 1);
}

TEST(DefaultOptionsGrpc, DefaultEndpointsDirectPathOverInterconnectDisabled) {
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}.set<storage_experimental::DirectPathXdsOverInterconnectOption>(
false),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(), "storage.googleapis.com");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.googleapis.com");
EXPECT_GE(options.get<GrpcNumChannelsOption>(), 4);
}

TEST(DefaultOptionsGrpc,
DefaultEndpointsDirectPathOverInterconnectUserEndpointOverride) {
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}
.set<storage_experimental::DirectPathXdsOverInterconnectOption>(true)
.set<EndpointOption>("custom-endpoint")
.set<AuthorityOption>("custom-authority"),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(), "custom-endpoint");
EXPECT_EQ(options.get<AuthorityOption>(), "custom-authority");
}

TEST(DefaultOptionsGrpc,
DefaultEndpointsDirectPathOverInterconnectUniverseDomainOverride) {
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}
.set<storage_experimental::DirectPathXdsOverInterconnectOption>(true)
.set<internal::UniverseDomainOption>("my-ud.net"),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(), "storage.my-ud.net");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.my-ud.net");
}

TEST(
DefaultOptionsGrpc,
DefaultEndpointsDirectPathOverInterconnectProgrammaticFalseOverridesEnvVar) {
ScopedEnvironment env("GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS_OVER_INTERCONNECT",
"true");
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}.set<storage_experimental::DirectPathXdsOverInterconnectOption>(
false),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(), "storage.googleapis.com");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.googleapis.com");
EXPECT_FALSE(
options.get<storage_experimental::DirectPathXdsOverInterconnectOption>());
EXPECT_GE(options.get<GrpcNumChannelsOption>(), 4);
}

TEST(DefaultOptionsGrpc,
DefaultEndpointsDirectPathOverInterconnectPreservesCustomAuthority) {
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}
.set<storage_experimental::DirectPathXdsOverInterconnectOption>(true)
.set<AuthorityOption>("custom-authority"),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(),
"google-c2p:///storage-direct.googleapis.com?force-xds");
EXPECT_EQ(options.get<AuthorityOption>(), "custom-authority");
EXPECT_EQ(options.get<GrpcNumChannelsOption>(), 1);
}

TEST(DefaultOptionsGrpc,
DefaultEndpointsDirectPathOverInterconnectUniverseDomainEnvVar) {
ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "my-ud.net");
auto mock_detector = std::make_shared<MockGcpDetector>();
EXPECT_CALL(*mock_detector, IsGoogleCloudBios())
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_detector, IsGoogleCloudServerless())
.WillRepeatedly(Return(false));

auto options = DefaultOptionsGrpc(
Options{}.set<storage_experimental::DirectPathXdsOverInterconnectOption>(
true),
mock_detector);
EXPECT_EQ(options.get<EndpointOption>(), "storage.my-ud.net");
EXPECT_EQ(options.get<AuthorityOption>(), "storage.my-ud.net");
}

TEST(DefaultOptionsGrpc, EndpointOptionsOverrideDefaults) {
ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "ud-env-var.net");

Expand Down
Loading