diff --git a/google/cloud/storage/client.cc b/google/cloud/storage/client.cc index 5cb0af53a4ca4..1758c361e5b70 100644 --- a/google/cloud/storage/client.cc +++ b/google/cloud/storage/client.cc @@ -13,19 +13,35 @@ // limitations under the License. #include "google/cloud/storage/client.h" +#include "google/cloud/storage/idempotency_policy.h" #include "google/cloud/storage/internal/base64.h" #include "google/cloud/storage/internal/connection_factory.h" +#include "google/cloud/storage/internal/unified_rest_credentials.h" +#include "google/cloud/storage/oauth2/credentials.h" +#include "google/cloud/storage/oauth2/google_credentials.h" #include "google/cloud/storage/oauth2/service_account_credentials.h" +#include "google/cloud/storage/options.h" #include "google/cloud/internal/absl_str_cat_quiet.h" +#include "google/cloud/internal/absl_str_join_quiet.h" #include "google/cloud/internal/curl_handle.h" #include "google/cloud/internal/curl_options.h" #include "google/cloud/internal/filesystem.h" +#include "google/cloud/internal/getenv.h" #include "google/cloud/internal/make_status.h" #include "google/cloud/internal/opentelemetry.h" +#include "google/cloud/internal/populate_common_options.h" +#include "google/cloud/internal/rest_options.h" +#include "google/cloud/internal/rest_response.h" +#include "google/cloud/internal/service_endpoint.h" #include "google/cloud/log.h" +#include "google/cloud/opentelemetry_options.h" +#include "google/cloud/universe_domain_options.h" #include "absl/strings/str_split.h" +#include #include #include +#include +#include #include #include #include @@ -387,8 +403,219 @@ std::string Client::EndpointAuthority() const { return std::string(endpoint_authority); } +// This magic number was obtained by experimentation summarized in #2657 +#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE +#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE (8 * 1024 * 1024) +#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE + +// This magic number was obtained by experimentation summarized in #2657 +#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE +#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE \ + (3 * 1024 * 1024 / 2) +#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE + +// This is a result of experiments performed in #2657. +#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE +#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE \ + (20 * 1024 * 1024L) +#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE + +#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT +#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT 120 +#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT + +// Define the defaults using a pre-processor macro, this allows the application +// developers to change the defaults for their application by compiling with +// different values. +#ifndef STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD +#define STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD std::chrono::minutes(15) +#endif // STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD + +#ifndef STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY +#define STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY std::chrono::seconds(1) +#endif // STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY + +#ifndef STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY +#define STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY std::chrono::minutes(5) +#endif // STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY + +#ifndef STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING +#define STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING 2.0 +#endif // STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING + +namespace { + +using ::google::cloud::internal::GetEnv; + +absl::optional GetEmulator() { + auto emulator = GetEnv("CLOUD_STORAGE_EMULATOR_ENDPOINT"); + if (emulator) return emulator; + return GetEnv("CLOUD_STORAGE_TESTBENCH_ENDPOINT"); +} + +std::size_t DefaultConnectionPoolSize() { + std::size_t nthreads = std::thread::hardware_concurrency(); + if (nthreads == 0) { + return 4; + } + return 4 * nthreads; +} + +} // namespace + namespace internal { +Options ApplyPolicy(Options opts, RetryPolicy const& p) { + opts.set(p.clone()); + return opts; +} + +Options ApplyPolicy(Options opts, BackoffPolicy const& p) { + opts.set(p.clone()); + return opts; +} + +Options ApplyPolicy(Options opts, IdempotencyPolicy const& p) { + opts.set(p.clone()); + return opts; +} + +Options DefaultOptions(std::shared_ptr credentials, + Options opts) { + auto ud = GetEnv("GOOGLE_CLOUD_UNIVERSE_DOMAIN"); + if (ud && !ud->empty()) { + opts.set(*std::move(ud)); + } + auto gcs_ep = google::cloud::internal::UniverseDomainEndpoint( + "https://storage.googleapis.com", opts); + auto iam_ep = absl::StrCat(google::cloud::internal::UniverseDomainEndpoint( + "https://iamcredentials.googleapis.com", opts), + "/v1"); + auto o = + Options{} + .set(std::move(credentials)) + .set(std::move(gcs_ep)) + .set(std::move(iam_ep)) + .set("v1") + .set(DefaultConnectionPoolSize()) + .set( + GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE) + .set( + GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE) + .set( + GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE) + .set(true) + .set(true) + .set(0) + .set(0) + .set(std::chrono::seconds( + GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT)) + .set(1) + .set(1) + .set( + LimitedTimeRetryPolicy( + STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD) + .clone()) + .set( + ExponentialBackoffPolicy( + STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY, + STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY, + STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING) + .clone()) + .set(AlwaysRetryIdempotencyPolicy().clone()); + + o = google::cloud::internal::MergeOptions(std::move(opts), std::move(o)); + // If the application did not set `DownloadStallTimeoutOption` then use the + // same value as `TransferStallTimeoutOption` (which could be the default + // value). Some applications need tighter timeouts for downloads, but longer + // timeouts for other transfers. + if (!o.has()) { + o.set(o.get()); + } + + auto emulator = GetEmulator(); + if (emulator.has_value()) { + o.set(*emulator).set(*emulator + + "/iamapi"); + } + + auto logging = GetEnv("CLOUD_STORAGE_ENABLE_TRACING"); + if (logging) { + for (auto c : absl::StrSplit(*logging, ',')) { + GCP_LOG(INFO) << "Enabling logging for " << c; + o.lookup().insert(std::string(c)); + } + } + + auto tracing = GetEnv("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING"); + if (tracing && !tracing->empty()) { + o.set(true); + } + + auto project_id = GetEnv("GOOGLE_CLOUD_PROJECT"); + if (project_id.has_value()) { + o.set(std::move(*project_id)); + } + + // Always apply the RestClient defaults, even if it is not in use. Now that we + // use the low-level initialization code in + // google/cloud/internal/curl_wrappers.cc, these are always needed. + namespace rest = ::google::cloud::rest_internal; + auto rest_defaults = Options{} + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()) + .set( + o.get()); + + // These two are not always present, but if they are, and only if they are, we + // need to map their value to the corresponding option in `rest_internal::`. + if (o.has()) { + rest_defaults.set( + o.get()); + } + if (o.has()) { + rest_defaults.set(o.get()); + } + + return google::cloud::internal::MergeOptions(std::move(o), + std::move(rest_defaults)); +} + +Options DefaultOptionsWithCredentials(Options opts) { + if (opts.has()) { + auto credentials = opts.get(); + return internal::DefaultOptions(std::move(credentials), std::move(opts)); + } + if (opts.has()) { + auto credentials = + internal::MapCredentials(*opts.get()); + return internal::DefaultOptions(std::move(credentials), std::move(opts)); + } + if (GetEmulator().has_value()) { + return internal::DefaultOptions( + internal::MapCredentials(*google::cloud::MakeInsecureCredentials()), + std::move(opts)); + } + auto credentials = + internal::MapCredentials(*google::cloud::MakeGoogleDefaultCredentials( + google::cloud::internal::MakeAuthOptions(opts))); + return internal::DefaultOptions(std::move(credentials), std::move(opts)); +} + Client ClientImplDetails::CreateWithDecorations( Options const& opts, std::shared_ptr connection) { return Client( diff --git a/google/cloud/storage/client.h b/google/cloud/storage/client.h index 6c9658c850189..a6f9ee70a2d50 100644 --- a/google/cloud/storage/client.h +++ b/google/cloud/storage/client.h @@ -15,7 +15,6 @@ #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H -#include "google/cloud/storage/client_options.h" #include "google/cloud/storage/hmac_key_metadata.h" #include "google/cloud/storage/internal/policy_document_request.h" #include "google/cloud/storage/internal/request_project_id.h" @@ -55,6 +54,23 @@ namespace internal { class NonResumableParallelUploadState; class ResumableParallelUploadState; struct ClientImplDetails; + +Options ApplyPolicy(Options opts, RetryPolicy const& p); +Options ApplyPolicy(Options opts, BackoffPolicy const& p); +Options ApplyPolicy(Options opts, IdempotencyPolicy const& p); + +inline Options ApplyPolicies(Options opts) { return opts; } + +template +Options ApplyPolicies(Options opts, P&& head, Policies&&... tail) { + opts = ApplyPolicy(std::move(opts), std::forward

(head)); + return ApplyPolicies(std::move(opts), std::forward(tail)...); +} + +Options DefaultOptions(std::shared_ptr credentials, + Options opts); +Options DefaultOptionsWithCredentials(Options opts); + } // namespace internal /** * The Google Cloud Storage (GCS) Client. diff --git a/google/cloud/storage/client_options.cc b/google/cloud/storage/client_options.cc deleted file mode 100644 index 34fa437fb07cb..0000000000000 --- a/google/cloud/storage/client_options.cc +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "google/cloud/storage/client_options.h" -#include "google/cloud/storage/internal/unified_rest_credentials.h" -#include "google/cloud/storage/oauth2/credentials.h" -#include "google/cloud/storage/oauth2/google_credentials.h" -#include "google/cloud/internal/absl_str_join_quiet.h" -#include "google/cloud/internal/curl_options.h" -#include "google/cloud/internal/getenv.h" -#include "google/cloud/internal/populate_common_options.h" -#include "google/cloud/internal/rest_options.h" -#include "google/cloud/internal/rest_response.h" -#include "google/cloud/internal/service_endpoint.h" -#include "google/cloud/log.h" -#include "google/cloud/opentelemetry_options.h" -#include "google/cloud/universe_domain_options.h" -#include "absl/strings/str_split.h" -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace cloud { -namespace storage { -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN - -using ::google::cloud::internal::GetEnv; - -namespace { - -absl::optional GetEmulator() { - auto emulator = GetEnv("CLOUD_STORAGE_EMULATOR_ENDPOINT"); - if (emulator) return emulator; - return GetEnv("CLOUD_STORAGE_TESTBENCH_ENDPOINT"); -} - -std::size_t DefaultConnectionPoolSize() { - std::size_t nthreads = std::thread::hardware_concurrency(); - if (nthreads == 0) { - return 4; - } - return 4 * nthreads; -} - -// This magic number was obtained by experimentation summarized in #2657 -#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE -#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE (8 * 1024 * 1024) -#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_BUFFER_SIZE - -// This magic number was obtained by experimentation summarized in #2657 -#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE -#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE \ - (3 * 1024 * 1024 / 2) -#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_BUFFER_SIZE - -// This is a result of experiments performed in #2657. -#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE -#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE \ - (20 * 1024 * 1024L) -#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE - -#ifndef GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT -#define GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT 120 -#endif // GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT - -// Define the defaults using a pre-processor macro, this allows the application -// developers to change the defaults for their application by compiling with -// different values. -#ifndef STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD -#define STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD std::chrono::minutes(15) -#endif // STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD - -#ifndef STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY -#define STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY std::chrono::seconds(1) -#endif // STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY - -#ifndef STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY -#define STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY std::chrono::minutes(5) -#endif // STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY - -#ifndef STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING -#define STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING 2.0 -#endif // STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING - -} // namespace - -namespace internal { - -std::string RestEndpoint(Options const& options) { - return GetEmulator().value_or(options.get()); -} - -std::string IamEndpoint(Options const& options) { - auto emulator = GetEmulator(); - if (emulator) return *emulator + "/iamapi"; - return options.get(); -} - -Options ApplyPolicy(Options opts, RetryPolicy const& p) { - opts.set(p.clone()); - return opts; -} - -Options ApplyPolicy(Options opts, BackoffPolicy const& p) { - opts.set(p.clone()); - return opts; -} - -Options ApplyPolicy(Options opts, IdempotencyPolicy const& p) { - opts.set(p.clone()); - return opts; -} - -Options DefaultOptions(std::shared_ptr credentials, - Options opts) { - auto ud = GetEnv("GOOGLE_CLOUD_UNIVERSE_DOMAIN"); - if (ud && !ud->empty()) { - opts.set(*std::move(ud)); - } - auto gcs_ep = google::cloud::internal::UniverseDomainEndpoint( - "https://storage.googleapis.com", opts); - auto iam_ep = absl::StrCat(google::cloud::internal::UniverseDomainEndpoint( - "https://iamcredentials.googleapis.com", opts), - "/v1"); - auto o = - Options{} - .set(std::move(credentials)) - .set(std::move(gcs_ep)) - .set(std::move(iam_ep)) - .set("v1") - .set(DefaultConnectionPoolSize()) - .set( - GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_BUFFER_SIZE) - .set( - GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_UPLOAD_BUFFER_SIZE) - .set( - GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_MAXIMUM_SIMPLE_UPLOAD_SIZE) - .set(true) - .set(true) - .set(0) - .set(0) - .set(std::chrono::seconds( - GOOGLE_CLOUD_CPP_STORAGE_DEFAULT_DOWNLOAD_STALL_TIMEOUT)) - .set(1) - .set(1) - .set( - LimitedTimeRetryPolicy( - STORAGE_CLIENT_DEFAULT_MAXIMUM_RETRY_PERIOD) - .clone()) - .set( - ExponentialBackoffPolicy( - STORAGE_CLIENT_DEFAULT_INITIAL_BACKOFF_DELAY, - STORAGE_CLIENT_DEFAULT_MAXIMUM_BACKOFF_DELAY, - STORAGE_CLIENT_DEFAULT_BACKOFF_SCALING) - .clone()) - .set(AlwaysRetryIdempotencyPolicy().clone()); - - o = google::cloud::internal::MergeOptions(std::move(opts), std::move(o)); - // If the application did not set `DownloadStallTimeoutOption` then use the - // same value as `TransferStallTimeoutOption` (which could be the default - // value). Some applications need tighter timeouts for downloads, but longer - // timeouts for other transfers. - if (!o.has()) { - o.set(o.get()); - } - - auto emulator = GetEmulator(); - if (emulator.has_value()) { - o.set(*emulator).set(*emulator + - "/iamapi"); - } - - auto logging = GetEnv("CLOUD_STORAGE_ENABLE_TRACING"); - if (logging) { - for (auto c : absl::StrSplit(*logging, ',')) { - GCP_LOG(INFO) << "Enabling logging for " << c; - o.lookup().insert(std::string(c)); - } - } - - auto tracing = GetEnv("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING"); - if (tracing && !tracing->empty()) { - o.set(true); - } - - auto project_id = GetEnv("GOOGLE_CLOUD_PROJECT"); - if (project_id.has_value()) { - o.set(std::move(*project_id)); - } - - // Always apply the RestClient defaults, even if it is not in use. Now that we - // use the low-level initialization code in - // google/cloud/internal/curl_wrappers.cc, these are always needed. - namespace rest = ::google::cloud::rest_internal; - auto rest_defaults = Options{} - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()) - .set( - o.get()); - - // These two are not always present, but if they are, and only if they are, we - // need to map their value to the corresponding option in `rest_internal::`. - if (o.has()) { - rest_defaults.set( - o.get()); - } - if (o.has()) { - rest_defaults.set(o.get()); - } - - return google::cloud::internal::MergeOptions(std::move(o), - std::move(rest_defaults)); -} - -Options DefaultOptionsWithCredentials(Options opts) { - if (opts.has()) { - auto credentials = opts.get(); - return internal::DefaultOptions(std::move(credentials), std::move(opts)); - } - if (opts.has()) { - auto credentials = - internal::MapCredentials(*opts.get()); - return internal::DefaultOptions(std::move(credentials), std::move(opts)); - } - if (GetEmulator().has_value()) { - return internal::DefaultOptions( - internal::MapCredentials(*google::cloud::MakeInsecureCredentials()), - std::move(opts)); - } - auto credentials = - internal::MapCredentials(*google::cloud::MakeGoogleDefaultCredentials( - google::cloud::internal::MakeAuthOptions(opts))); - return internal::DefaultOptions(std::move(credentials), std::move(opts)); -} - -} // namespace internal - -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END -} // namespace storage -} // namespace cloud -} // namespace google diff --git a/google/cloud/storage/client_options.h b/google/cloud/storage/client_options.h deleted file mode 100644 index 0b32932be6c0b..0000000000000 --- a/google/cloud/storage/client_options.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_OPTIONS_H -#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_OPTIONS_H - -#include "google/cloud/storage/oauth2/credentials.h" -#include "google/cloud/storage/options.h" -#include "google/cloud/storage/version.h" -#include "google/cloud/common_options.h" -#include "google/cloud/options.h" -#include -#include -#include - -namespace google { -namespace cloud { -namespace storage { -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN -namespace internal { -std::string RestEndpoint(Options const&); -std::string IamEndpoint(Options const&); - -Options ApplyPolicy(Options opts, RetryPolicy const& p); -Options ApplyPolicy(Options opts, BackoffPolicy const& p); -Options ApplyPolicy(Options opts, IdempotencyPolicy const& p); - -inline Options ApplyPolicies(Options opts) { return opts; } - -template -Options ApplyPolicies(Options opts, P&& head, Policies&&... tail) { - opts = ApplyPolicy(std::move(opts), std::forward

(head)); - return ApplyPolicies(std::move(opts), std::forward(tail)...); -} - -Options DefaultOptions(std::shared_ptr credentials, - Options opts); -Options DefaultOptionsWithCredentials(Options opts); - -} // namespace internal - -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END -} // namespace storage -} // namespace cloud -} // namespace google - -#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_OPTIONS_H diff --git a/google/cloud/storage/client_options_test.cc b/google/cloud/storage/client_options_test.cc deleted file mode 100644 index dea07878b0cfb..0000000000000 --- a/google/cloud/storage/client_options_test.cc +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "google/cloud/storage/client_options.h" -#include "google/cloud/storage/oauth2/google_credentials.h" -#include "google/cloud/storage/options.h" -#include "google/cloud/internal/curl_options.h" -#include "google/cloud/internal/filesystem.h" -#include "google/cloud/internal/random.h" -#include "google/cloud/internal/rest_options.h" -#include "google/cloud/internal/rest_response.h" -#include "google/cloud/opentelemetry_options.h" -#include "google/cloud/testing_util/scoped_environment.h" -#include "google/cloud/testing_util/setenv.h" -#include "google/cloud/testing_util/status_matchers.h" -#include "google/cloud/universe_domain_options.h" -#include -#include -#include -#include -#include - -namespace google { -namespace cloud { -namespace storage { -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN - -using ::google::cloud::testing_util::ScopedEnvironment; -using ::testing::UnorderedElementsAre; - -namespace { -class ClientOptionsTest : public ::testing::Test { - public: - ClientOptionsTest() - : enable_tracing_("CLOUD_STORAGE_ENABLE_TRACING", {}), - endpoint_("CLOUD_STORAGE_EMULATOR_ENDPOINT", {}), - old_endpoint_("CLOUD_STORAGE_TESTBENCH_ENDPOINT", {}), - generator_(std::random_device{}()) {} - - std::string CreateRandomFileName() { - // When running on the internal Google CI systems we cannot write to the - // local directory. GTest has a good temporary directory in that case. - return google::cloud::internal::PathAppend( - ::testing::TempDir(), - google::cloud::internal::Sample( - generator_, 8, "abcdefghijklmnopqrstuvwxyz0123456789") + - ".json"); - } - - protected: - ScopedEnvironment enable_tracing_; - ScopedEnvironment endpoint_; - ScopedEnvironment old_endpoint_; - google::cloud::internal::DefaultPRNG generator_; -}; - -TEST_F(ClientOptionsTest, EndpointsDefault) { - testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", - {}); - auto options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("https://storage.googleapis.com", - options.get()); - EXPECT_EQ("https://iamcredentials.googleapis.com/v1", - internal::IamEndpoint(options)); -} - -TEST_F(ClientOptionsTest, EndpointsOverride) { - testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", - {}); - auto options = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set("http://127.0.0.1.nip.io:1234")); - EXPECT_EQ("http://127.0.0.1.nip.io:1234", options.get()); - EXPECT_EQ("https://iamcredentials.googleapis.com/v1", - internal::IamEndpoint(options)); -} - -TEST_F(ClientOptionsTest, EndpointsEmulator) { - testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", - "http://localhost:1234"); - auto options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("http://localhost:1234", options.get()); - EXPECT_EQ("http://localhost:1234/iamapi", internal::IamEndpoint(options)); -} - -TEST_F(ClientOptionsTest, OldEndpointsEmulator) { - google::cloud::testing_util::UnsetEnv("CLOUD_STORAGE_EMULATOR_ENDPOINT"); - testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_TESTBENCH_ENDPOINT", - "http://localhost:1234"); - auto options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("http://localhost:1234", options.get()); - EXPECT_EQ("http://localhost:1234/iamapi", internal::IamEndpoint(options)); -} - -TEST_F(ClientOptionsTest, DefaultOptions) { - auto o = internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("https://storage.googleapis.com", o.get()); - - // Verify any set values are respected overridden. - o = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set("https://private.googleapis.com")); - EXPECT_EQ("https://private.googleapis.com", o.get()); - - o = internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("https://storage.googleapis.com", o.get()); - EXPECT_EQ("https://iamcredentials.googleapis.com/v1", - o.get()); - - EXPECT_EQ("v1", o.get()); - EXPECT_LT(0, o.get()); - EXPECT_LT(0, o.get()); - EXPECT_LT(0, o.get()); - EXPECT_LE(0, o.get()); - EXPECT_TRUE(o.get()); - EXPECT_TRUE(o.get()); - EXPECT_EQ(0, o.get()); - EXPECT_EQ(0, o.get()); - EXPECT_LT(std::chrono::seconds(0), o.get()); - EXPECT_LT(0, o.get()); - EXPECT_LT(std::chrono::seconds(0), o.get()); - EXPECT_LT(0, o.get()); - - namespace rest = ::google::cloud::rest_internal; - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - EXPECT_EQ(o.get(), - o.get()); - - EXPECT_FALSE(o.has()); - EXPECT_FALSE(o.has()); -} - -TEST_F(ClientOptionsTest, IncorporatesUniverseDomain) { - auto o = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set( - "my-ud.net")); - EXPECT_EQ(o.get(), "https://storage.my-ud.net"); - EXPECT_EQ(o.get(), "https://iamcredentials.my-ud.net/v1"); -} - -TEST_F(ClientOptionsTest, IncorporatesUniverseDomainEnvVar) { - ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "ud-env-var.net"); - - auto o = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set( - "ud-option.net")); - EXPECT_EQ(o.get(), "https://storage.ud-env-var.net"); - EXPECT_EQ(o.get(), - "https://iamcredentials.ud-env-var.net/v1"); -} - -TEST_F(ClientOptionsTest, CustomEndpointOverridesUniverseDomain) { - ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "ud-env-var.net"); - - auto o = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{} - .set("https://custom-storage.googleapis.com") - .set( - "https://custom-iamcredentials.googleapis.com/v1") - .set("ud-option.net")); - EXPECT_EQ(o.get(), - "https://custom-storage.googleapis.com"); - EXPECT_EQ(o.get(), - "https://custom-iamcredentials.googleapis.com/v1"); -} - -TEST_F(ClientOptionsTest, HttpVersion) { - namespace rest = ::google::cloud::rest_internal; - auto const options = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set("2.0")); - EXPECT_EQ("2.0", options.get()); -} - -TEST_F(ClientOptionsTest, CAPathOption) { - namespace rest = ::google::cloud::rest_internal; - auto const options = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set("test-only")); - EXPECT_EQ("test-only", options.get()); -} - -TEST_F(ClientOptionsTest, LoggingWithoutEnv) { - ScopedEnvironment env_common("GOOGLE_CLOUD_CPP_ENABLE_TRACING", - absl::nullopt); - ScopedEnvironment env("CLOUD_STORAGE_ENABLE_TRACING", absl::nullopt); - auto const options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_FALSE(options.has()); -} - -TEST_F(ClientOptionsTest, LoggingWithEnv) { - ScopedEnvironment env_common("GOOGLE_CLOUD_CPP_ENABLE_TRACING", - absl::nullopt); - ScopedEnvironment env("CLOUD_STORAGE_ENABLE_TRACING", "rpc,http"); - auto const options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_THAT(options.get(), - UnorderedElementsAre("rpc", "http")); -} - -TEST_F(ClientOptionsTest, TracingWithoutEnv) { - ScopedEnvironment env("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING", - absl::nullopt); - auto options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_FALSE(options.get()); - - options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), - Options{}.set(true)); - EXPECT_TRUE(options.get()); -} - -TEST_F(ClientOptionsTest, TracingWithEnv) { - ScopedEnvironment env("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING", "ON"); - auto const options = internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{}.set(false)); - EXPECT_TRUE(options.get()); -} - -TEST_F(ClientOptionsTest, ProjectIdWithoutEnv) { - ScopedEnvironment env("GOOGLE_CLOUD_PROJECT", absl::nullopt); - auto const options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_FALSE(options.has()); -} - -TEST_F(ClientOptionsTest, ProjecIdtWithEnv) { - ScopedEnvironment env("GOOGLE_CLOUD_PROJECT", "my-project"); - auto const options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); - EXPECT_EQ("my-project", options.get()); -} - -TEST_F(ClientOptionsTest, OverrideWithRestInternal) { - namespace rest = ::google::cloud::rest_internal; - auto const options = - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), - Options{} - .set(1234) - .set(2345)); - EXPECT_EQ(1234, options.get()); - EXPECT_EQ(2345, options.get()); -} - -TEST_F(ClientOptionsTest, Timeouts) { - EXPECT_EQ(std::chrono::seconds(42), - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), - Options{}.set( - std::chrono::seconds(42))) - .get()); - - EXPECT_EQ(std::chrono::seconds(7), - internal::DefaultOptions( - oauth2::CreateAnonymousCredentials(), - Options{} - .set(std::chrono::seconds(42)) - .set(std::chrono::seconds(7))) - .get()); - - EXPECT_EQ(std::chrono::seconds(7), - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), - Options{}.set( - std::chrono::seconds(7))) - .get()); - - EXPECT_NE( - std::chrono::seconds(0), - internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), Options{}) - .get()); -} - -} // namespace -GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END -} // namespace storage -} // namespace cloud -} // namespace google diff --git a/google/cloud/storage/client_test.cc b/google/cloud/storage/client_test.cc index 270a0b918d46e..f3dd8ae3a7310 100644 --- a/google/cloud/storage/client_test.cc +++ b/google/cloud/storage/client_test.cc @@ -17,15 +17,25 @@ #include "google/cloud/storage/retry_policy.h" #include "google/cloud/storage/testing/canonical_errors.h" #include "google/cloud/storage/testing/mock_client.h" +#include "google/cloud/internal/curl_options.h" +#include "google/cloud/internal/filesystem.h" #include "google/cloud/internal/getenv.h" +#include "google/cloud/internal/random.h" +#include "google/cloud/internal/rest_options.h" +#include "google/cloud/internal/rest_response.h" #include "google/cloud/opentelemetry_options.h" #include "google/cloud/testing_util/mock_backoff_policy.h" #include "google/cloud/testing_util/opentelemetry_matchers.h" #include "google/cloud/testing_util/scoped_environment.h" +#include "google/cloud/testing_util/setenv.h" #include "google/cloud/testing_util/status_matchers.h" +#include "google/cloud/universe_domain_options.h" #include #include +#include +#include #include +#include #include #include @@ -41,6 +51,7 @@ using ::google::cloud::testing_util::ScopedEnvironment; using ::testing::ElementsAre; using ::testing::NotNull; using ::testing::Return; +using ::testing::UnorderedElementsAre; class ObservableRetryPolicy : public LimitedErrorCountRetryPolicy { public: @@ -79,6 +90,13 @@ class ObservableBackoffPolicy : public ExponentialBackoffPolicy { int ObservableBackoffPolicy::on_completion_call_count_; class ClientTest : public ::testing::Test { + public: + ClientTest() + : enable_tracing_("CLOUD_STORAGE_ENABLE_TRACING", {}), + endpoint_("CLOUD_STORAGE_EMULATOR_ENDPOINT", {}), + old_endpoint_("CLOUD_STORAGE_TESTBENCH_ENDPOINT", {}), + generator_(std::random_device{}()) {} + protected: void SetUp() override { mock_ = std::make_shared(); @@ -92,6 +110,10 @@ class ClientTest : public ::testing::Test { } std::shared_ptr mock_; + ScopedEnvironment enable_tracing_; + ScopedEnvironment endpoint_; + ScopedEnvironment old_endpoint_; + google::cloud::internal::DefaultPRNG generator_; }; TEST_F(ClientTest, Equality) { @@ -236,6 +258,245 @@ TEST_F(ClientTest, OTelDisableTracing) { ElementsAre("RestStub", "LoggingStub", "StorageConnectionImpl")); } +TEST_F(ClientTest, EndpointsDefault) { + testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", + {}); + auto options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("https://storage.googleapis.com", + options.get()); + EXPECT_EQ("https://iamcredentials.googleapis.com/v1", + options.get()); +} + +TEST_F(ClientTest, EndpointsOverride) { + testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", + {}); + auto options = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set("http://127.0.0.1.nip.io:1234")); + EXPECT_EQ("http://127.0.0.1.nip.io:1234", options.get()); + EXPECT_EQ("https://iamcredentials.googleapis.com/v1", + options.get()); +} + +TEST_F(ClientTest, EndpointsEmulator) { + testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_EMULATOR_ENDPOINT", + "http://localhost:1234"); + auto options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("http://localhost:1234", options.get()); + EXPECT_EQ("http://localhost:1234/iamapi", options.get()); +} + +TEST_F(ClientTest, OldEndpointsEmulator) { + google::cloud::testing_util::UnsetEnv("CLOUD_STORAGE_EMULATOR_ENDPOINT"); + testing_util::ScopedEnvironment endpoint("CLOUD_STORAGE_TESTBENCH_ENDPOINT", + "http://localhost:1234"); + auto options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("http://localhost:1234", options.get()); + EXPECT_EQ("http://localhost:1234/iamapi", options.get()); +} + +TEST_F(ClientTest, DefaultOptions) { + auto o = internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("https://storage.googleapis.com", o.get()); + + // Verify any set values are respected overridden. + o = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set("https://private.googleapis.com")); + EXPECT_EQ("https://private.googleapis.com", o.get()); + + o = internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("https://storage.googleapis.com", o.get()); + EXPECT_EQ("https://iamcredentials.googleapis.com/v1", + o.get()); + + EXPECT_EQ("v1", o.get()); + EXPECT_LT(0, o.get()); + EXPECT_LT(0, o.get()); + EXPECT_LT(0, o.get()); + EXPECT_LE(0, o.get()); + EXPECT_TRUE(o.get()); + EXPECT_TRUE(o.get()); + EXPECT_EQ(0, o.get()); + EXPECT_EQ(0, o.get()); + EXPECT_LT(std::chrono::seconds(0), o.get()); + EXPECT_LT(0, o.get()); + EXPECT_LT(std::chrono::seconds(0), o.get()); + EXPECT_LT(0, o.get()); + + namespace rest = ::google::cloud::rest_internal; + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + EXPECT_EQ(o.get(), + o.get()); + + EXPECT_FALSE(o.has()); + EXPECT_FALSE(o.has()); +} + +TEST_F(ClientTest, IncorporatesUniverseDomain) { + auto o = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set( + "my-ud.net")); + EXPECT_EQ(o.get(), "https://storage.my-ud.net"); + EXPECT_EQ(o.get(), "https://iamcredentials.my-ud.net/v1"); +} + +TEST_F(ClientTest, IncorporatesUniverseDomainEnvVar) { + ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "ud-env-var.net"); + + auto o = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set( + "ud-option.net")); + EXPECT_EQ(o.get(), "https://storage.ud-env-var.net"); + EXPECT_EQ(o.get(), + "https://iamcredentials.ud-env-var.net/v1"); +} + +TEST_F(ClientTest, CustomEndpointOverridesUniverseDomain) { + ScopedEnvironment ud("GOOGLE_CLOUD_UNIVERSE_DOMAIN", "ud-env-var.net"); + + auto o = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{} + .set("https://custom-storage.googleapis.com") + .set( + "https://custom-iamcredentials.googleapis.com/v1") + .set("ud-option.net")); + EXPECT_EQ(o.get(), + "https://custom-storage.googleapis.com"); + EXPECT_EQ(o.get(), + "https://custom-iamcredentials.googleapis.com/v1"); +} + +TEST_F(ClientTest, HttpVersion) { + namespace rest = ::google::cloud::rest_internal; + auto const options = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set("2.0")); + EXPECT_EQ("2.0", options.get()); +} + +TEST_F(ClientTest, CAPathOption) { + namespace rest = ::google::cloud::rest_internal; + auto const options = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set("test-only")); + EXPECT_EQ("test-only", options.get()); +} + +TEST_F(ClientTest, LoggingWithoutEnv) { + ScopedEnvironment env_common("GOOGLE_CLOUD_CPP_ENABLE_TRACING", + absl::nullopt); + ScopedEnvironment env("CLOUD_STORAGE_ENABLE_TRACING", absl::nullopt); + auto const options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_FALSE(options.has()); +} + +TEST_F(ClientTest, LoggingWithEnv) { + ScopedEnvironment env_common("GOOGLE_CLOUD_CPP_ENABLE_TRACING", + absl::nullopt); + ScopedEnvironment env("CLOUD_STORAGE_ENABLE_TRACING", "rpc,http"); + auto const options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_THAT(options.get(), + UnorderedElementsAre("rpc", "http")); +} + +TEST_F(ClientTest, TracingWithoutEnv) { + ScopedEnvironment env("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING", + absl::nullopt); + auto options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_FALSE(options.get()); + + options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), + Options{}.set(true)); + EXPECT_TRUE(options.get()); +} + +TEST_F(ClientTest, TracingWithEnv) { + ScopedEnvironment env("GOOGLE_CLOUD_CPP_OPENTELEMETRY_TRACING", "ON"); + auto const options = internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{}.set(false)); + EXPECT_TRUE(options.get()); +} + +TEST_F(ClientTest, ProjectIdWithoutEnv) { + ScopedEnvironment env("GOOGLE_CLOUD_PROJECT", absl::nullopt); + auto const options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_FALSE(options.has()); +} + +TEST_F(ClientTest, ProjectIdtWithEnv) { + ScopedEnvironment env("GOOGLE_CLOUD_PROJECT", "my-project"); + auto const options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), {}); + EXPECT_EQ("my-project", options.get()); +} + +TEST_F(ClientTest, OverrideWithRestInternal) { + namespace rest = ::google::cloud::rest_internal; + auto const options = + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), + Options{} + .set(1234) + .set(2345)); + EXPECT_EQ(1234, options.get()); + EXPECT_EQ(2345, options.get()); +} + +TEST_F(ClientTest, Timeouts) { + EXPECT_EQ(std::chrono::seconds(42), + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), + Options{}.set( + std::chrono::seconds(42))) + .get()); + + EXPECT_EQ(std::chrono::seconds(7), + internal::DefaultOptions( + oauth2::CreateAnonymousCredentials(), + Options{} + .set(std::chrono::seconds(42)) + .set(std::chrono::seconds(7))) + .get()); + + EXPECT_EQ(std::chrono::seconds(7), + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), + Options{}.set( + std::chrono::seconds(7))) + .get()); + + EXPECT_NE( + std::chrono::seconds(0), + internal::DefaultOptions(oauth2::CreateAnonymousCredentials(), Options{}) + .get()); +} + } // namespace GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END } // namespace storage diff --git a/google/cloud/storage/google_cloud_cpp_storage.bzl b/google/cloud/storage/google_cloud_cpp_storage.bzl index dd30262951bab..7b1dda7134f8e 100644 --- a/google/cloud/storage/google_cloud_cpp_storage.bzl +++ b/google/cloud/storage/google_cloud_cpp_storage.bzl @@ -36,7 +36,6 @@ google_cloud_cpp_storage_hdrs = [ "bucket_versioning.h", "bucket_website.h", "client.h", - "client_options.h", "download_options.h", "enable_object_retention.h", "hash_mismatch_error.h", @@ -170,7 +169,6 @@ google_cloud_cpp_storage_srcs = [ "bucket_retention_policy.cc", "bucket_soft_delete_policy.cc", "client.cc", - "client_options.cc", "hashing_options.cc", "hmac_key_metadata.cc", "iam_policy.cc", diff --git a/google/cloud/storage/google_cloud_cpp_storage.cmake b/google/cloud/storage/google_cloud_cpp_storage.cmake index 65a220d631b7b..c374c34ce4a34 100644 --- a/google/cloud/storage/google_cloud_cpp_storage.cmake +++ b/google/cloud/storage/google_cloud_cpp_storage.cmake @@ -54,8 +54,6 @@ add_library( bucket_website.h client.cc client.h - client_options.cc - client_options.h download_options.h enable_object_retention.h hash_mismatch_error.h @@ -433,7 +431,6 @@ if (BUILD_TESTING) client_object_acl_test.cc client_object_copy_test.cc client_object_test.cc - client_options_test.cc client_service_account_test.cc client_sign_policy_document_test.cc client_sign_url_test.cc diff --git a/google/cloud/storage/internal/grpc/default_options.cc b/google/cloud/storage/internal/grpc/default_options.cc index abd150c40d9ea..77cfc1803f893 100644 --- a/google/cloud/storage/internal/grpc/default_options.cc +++ b/google/cloud/storage/internal/grpc/default_options.cc @@ -13,7 +13,6 @@ // limitations under the License. #include "google/cloud/storage/internal/grpc/default_options.h" -#include "google/cloud/storage/client_options.h" #include "google/cloud/storage/grpc_plugin.h" #include "google/cloud/storage/options.h" #include "google/cloud/common_options.h" diff --git a/google/cloud/storage/internal/grpc/stub.cc b/google/cloud/storage/internal/grpc/stub.cc index 9a7120c6ebae8..461310381baee 100644 --- a/google/cloud/storage/internal/grpc/stub.cc +++ b/google/cloud/storage/internal/grpc/stub.cc @@ -30,6 +30,7 @@ #include "google/cloud/storage/internal/grpc/split_write_object_data.h" #include "google/cloud/storage/internal/grpc/synthetic_self_link.h" #include "google/cloud/storage/internal/storage_stub_factory.h" +#include "google/cloud/storage/options.h" #include "google/cloud/internal/big_endian.h" #include "google/cloud/internal/invoke_result.h" #include "google/cloud/internal/make_status.h" diff --git a/google/cloud/storage/internal/grpc/stub.h b/google/cloud/storage/internal/grpc/stub.h index 71b216b7be62a..9e6024bdb781e 100644 --- a/google/cloud/storage/internal/grpc/stub.h +++ b/google/cloud/storage/internal/grpc/stub.h @@ -15,7 +15,6 @@ #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_GRPC_STUB_H #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_GRPC_STUB_H -#include "google/cloud/storage/client_options.h" #include "google/cloud/storage/internal/generic_stub.h" #include "google/cloud/storage/version.h" #include "google/cloud/background_threads.h" diff --git a/google/cloud/storage/internal/grpc/stub_insert_object_media_test.cc b/google/cloud/storage/internal/grpc/stub_insert_object_media_test.cc index f3f207b9a1e00..3318c9fbba411 100644 --- a/google/cloud/storage/internal/grpc/stub_insert_object_media_test.cc +++ b/google/cloud/storage/internal/grpc/stub_insert_object_media_test.cc @@ -14,6 +14,7 @@ #include "google/cloud/storage/internal/grpc/stub.h" #include "google/cloud/storage/oauth2/google_credentials.h" +#include "google/cloud/storage/options.h" #include "google/cloud/storage/testing/mock_storage_stub.h" #include "google/cloud/grpc_options.h" #include "google/cloud/testing_util/is_proto_equal.h" diff --git a/google/cloud/storage/internal/grpc/stub_read_object_test.cc b/google/cloud/storage/internal/grpc/stub_read_object_test.cc index 5f9fded7cda04..ea3ddea3cbf2a 100644 --- a/google/cloud/storage/internal/grpc/stub_read_object_test.cc +++ b/google/cloud/storage/internal/grpc/stub_read_object_test.cc @@ -14,6 +14,7 @@ #include "google/cloud/storage/internal/grpc/object_read_source.h" #include "google/cloud/storage/internal/grpc/stub.h" +#include "google/cloud/storage/options.h" #include "google/cloud/storage/testing/mock_storage_stub.h" #include "google/cloud/grpc_options.h" #include "google/cloud/options.h" diff --git a/google/cloud/storage/internal/grpc/stub_upload_chunk_test.cc b/google/cloud/storage/internal/grpc/stub_upload_chunk_test.cc index 2c42cb69d45df..a50a5b6cfefd9 100644 --- a/google/cloud/storage/internal/grpc/stub_upload_chunk_test.cc +++ b/google/cloud/storage/internal/grpc/stub_upload_chunk_test.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "google/cloud/storage/internal/grpc/stub.h" +#include "google/cloud/storage/options.h" #include "google/cloud/storage/testing/mock_storage_stub.h" #include "google/cloud/grpc_options.h" #include "google/cloud/options.h" diff --git a/google/cloud/storage/internal/rest/stub.cc b/google/cloud/storage/internal/rest/stub.cc index 6c5235773058b..62acc29fc847e 100644 --- a/google/cloud/storage/internal/rest/stub.cc +++ b/google/cloud/storage/internal/rest/stub.cc @@ -13,7 +13,6 @@ // limitations under the License. #include "google/cloud/storage/internal/rest/stub.h" -#include "google/cloud/storage/client_options.h" #include "google/cloud/storage/internal/bucket_access_control_parser.h" #include "google/cloud/storage/internal/bucket_metadata_parser.h" #include "google/cloud/storage/internal/bucket_requests.h" @@ -46,6 +45,7 @@ namespace internal { namespace rest = google::cloud::rest_internal; using ::google::cloud::internal::AuthHeaderError; +using ::google::cloud::internal::GetEnv; using ::google::cloud::internal::UrlEncode; namespace { @@ -134,6 +134,22 @@ Status AddHeaders(Options const& options, RestRequestBuilder& builder) { return {}; } +absl::optional GetEmulator() { + auto emulator = GetEnv("CLOUD_STORAGE_EMULATOR_ENDPOINT"); + if (emulator) return emulator; + return GetEnv("CLOUD_STORAGE_TESTBENCH_ENDPOINT"); +} + +std::string RestEndpoint(Options const& options) { + return GetEmulator().value_or(options.get()); +} + +std::string IamEndpoint(Options const& options) { + auto emulator = GetEmulator(); + if (emulator) return *emulator + "/iamapi"; + return options.get(); +} + } // namespace RestStub::RestStub(Options options) diff --git a/google/cloud/storage/oauth2/service_account_credentials.cc b/google/cloud/storage/oauth2/service_account_credentials.cc index 963a6ca62ab01..25a1bc4ce2f4e 100644 --- a/google/cloud/storage/oauth2/service_account_credentials.cc +++ b/google/cloud/storage/oauth2/service_account_credentials.cc @@ -13,7 +13,6 @@ // limitations under the License. #include "google/cloud/storage/oauth2/service_account_credentials.h" -#include "google/cloud/storage/client_options.h" #include "google/cloud/storage/internal/base64.h" #include "google/cloud/storage/internal/make_jwt_assertion.h" #include "google/cloud/internal/absl_str_join_quiet.h" diff --git a/google/cloud/storage/storage_client_unit_tests.bzl b/google/cloud/storage/storage_client_unit_tests.bzl index 64bfb4611ebf5..065d4f6240a4b 100644 --- a/google/cloud/storage/storage_client_unit_tests.bzl +++ b/google/cloud/storage/storage_client_unit_tests.bzl @@ -31,7 +31,6 @@ storage_client_unit_tests = [ "client_object_acl_test.cc", "client_object_copy_test.cc", "client_object_test.cc", - "client_options_test.cc", "client_service_account_test.cc", "client_sign_policy_document_test.cc", "client_sign_url_test.cc",