# `google-cloud-cpp` v3 Migration Guide

This document helps users of previous major versions (v1.x.y, v2.x.y) of the
`google-cloud-cpp` SDK migrate to a release on the v3.x.y series.

While this repository does not strictly follow semver, it does use the major
version number to indicate large breaking changes. We strive to balance the
frequency in which we introduce breaking changes with improvements to the SDK.
Since our most recent major version increment, about 3 years ago, we have added
new API surfaces that supersede the previous deprecated types and functions. As
part of the v3 release series, we are decommissioning those deprecated API
surfaces.

## C++17

Depending on your build system of choice, you should set the appropriate flag
for your compiler if it does not already default to `--std=c++17` or higher.

## Dependencies

### Previously Optional Dependencies that are now Required

- `libcurl`
- `nlohmann_json`
- `opentelemetry-cpp`

### Relocated Dependencies

- `crc32c` google-cloud-cpp now uses the crc32c implementation in Abseil.

## Build system changes

### Bazel

<details>
<summary>google-cloud-cpp module in Bazel Central Registry</summary>

Bazel is moving away from WORKSPACE file support to using modules from the Bazel
Central Registry. Part of the v3.x.y release series includes supporting the new
[google-cloud-cpp](https://registry.bazel.build/modules/google_cloud_cpp) Bazel
module which can be added to your `MODULE.bazel` file as a dependency.

google-cloud-cpp will support WORKSPACE files until Bazel 8 reaches end of
support (2027/12). However, some dependencies may stop supporting WORKSPACE
files before then which will limit what dependency versions can be used via
WORKSPACE.

</details>

### CMake

<details>
<summary>Removed backward compatible proto interface libraries.</summary>

If your application links directly to one of these decommissioned proto
libraries, you should update your CMakeLists.txt with the preferred proto
library name.

| Library                    | Decommissioned Proto Library          | Preferred Proto Library                |
| -------------------------- | ------------------------------------- | -------------------------------------- |
| google/cloud/dialogflow_es | cloud_dialogflow_v2_protos            | google-cloud-cpp::dialogflow_es_protos |
| google/cloud/logging       | logging_type_protos                   | google-cloud-cpp::logging_protos       |
| google/cloud/logging       | logging_type_type_protos              | google-cloud-cpp::logging_protos       |
| google/cloud/speech        | cloud_speech_protos                   | google-cloud-cpp::speech_protos        |
| google/cloud/texttospeech  | cloud_texttospeech_protos             | google-cloud-cpp::texttospeech_protos  |
| google/cloud/trace         | devtools_cloudtrace_v2_tracing_protos | google-cloud-cpp::trace_protos         |
| google/cloud/trace         | devtools_cloudtrace_v2_trace_protos   | google-cloud-cpp::trace_protos         |

</details>

## Decommissioned API Surfaces

### Common

<details>
<summary>Removed <code>v1</code> inline namespace alias.
</summary>

Omit the `v1` namespace for unversioned libraries:

- Bigtable
- PubSub
- Spanner
- Storage

For example, code that used to look like this:

**Before:**

```cpp

google::cloud::v1::pubsub::Publisher publisher;
```

Should be changed to this:

**After:**

```cpp
google::cloud::pubsub::Publisher publisher;
```

</details>

<details>
<summary>Removed <code>gcpcxxV1</code> inline namespace alias.
</summary>

Omit the `gcpcxxV1` namespace from versioned libraries. The version is now part
of the service namespace.

For example, code that used to look like this:

**Before:**

```cpp

google::cloud::bigquery_storage_v1::gcpcxxV1::BigQueryReadClient client;
```

Should be changed to this:

**After:**

```cpp
google::cloud::bigquery_storage_v1::BigQueryReadClient client;
```

</details>

<details>
<summary>Removed <code>google::cloud::grpc_utils</code> namespace and headers.
</summary>

Types that were previously defined in both `google::cloud::grpc_utils` and
`google::cloud` now only exist in `google::cloud`.

For example, code that used to look like this:

**Before:**

```cpp
#include "google/cloud/grpc_utils/completion_queue.h

google::cloud::grpc_utils::CompletionQueue cq;
```

Should be changed to this:

**After:**

```cpp
#include "google/cloud/completion_queue.h

google::cloud::CompletionQueue cq;
```

</details>

<details>
<summary>Removed unversioned forwarding headers.
</summary>

We created some early libraries without version and/or service directories. For
backwards compatibility, forwarding headers were left at parent directory that
pointed at the first version of the library:

- google/cloud/accessapproval
- google/cloud/accesscontextmanager
- google/cloud/apigateway
- google/cloud/apigeeconnect
- google/cloud/apikeys
- google/cloud/appengine
- google/cloud/artifactregistry
- google/cloud/asset
- google/cloud/assuredworkloads
- google/cloud/automl
- google/cloud/baremetalsolution
- google/cloud/batch
- google/cloud/beyondcorp
- google/cloud/bigquery
- google/cloud/billing
- google/cloud/binaryauthorization
- google/cloud/certificatemanager
- google/cloud/channel
- google/cloud/cloudbuild
- google/cloud/composer
- google/cloud/connectors
- google/cloud/contactcenterinsights
- google/cloud/container
- google/cloud/containeranalysis
- google/cloud/datacatalog
- google/cloud/datamigration
- google/cloud/dataplex
- google/cloud/dataproc
- google/cloud/datastream
- google/cloud/deploy
- google/cloud/dlp
- google/cloud/documentai
- google/cloud/edgecontainer
- google/cloud/eventarc
- google/cloud/filestore
- google/cloud/functions
- google/cloud/gkehub
- google/cloud/iam
- google/cloud/iap
- google/cloud/ids
- google/cloud/kms
- google/cloud/language
- google/cloud/logging
- google/cloud/managedidentities
- google/cloud/memcache
- google/cloud/monitoring
- google/cloud/networkconnectivity
- google/cloud/networkmanagement
- google/cloud/notebooks
- google/cloud/optimization
- google/cloud/orgpolicy
- google/cloud/osconfig
- google/cloud/oslogin
- google/cloud/policytroubleshooter
- google/cloud/privateca
- google/cloud/profiler
- google/cloud/recommender
- google/cloud/redis
- google/cloud/resourcemanager
- google/cloud/retail
- google/cloud/run
- google/cloud/scheduler
- google/cloud/secretmanager
- google/cloud/securitycenter
- google/cloud/servicecontrol
- google/cloud/servicedirectory
- google/cloud/servicemanagement
- google/cloud/serviceusage
- google/cloud/shell
- google/cloud/speech
- google/cloud/storagetransfer
- google/cloud/talent
- google/cloud/tasks
- google/cloud/texttospeech
- google/cloud/tpu
- google/cloud/trace
- google/cloud/translate
- google/cloud/video
- google/cloud/videointelligence
- google/cloud/vision
- google/cloud/vmmigration
- google/cloud/vpcaccess
- google/cloud/webrisk
- google/cloud/websecurityscanner
- google/cloud/workflows

For example, code that used to look like this:

**Before:**

```cpp
#include "google/cloud/bigquery/bigquery_read_client.h"
```

Should be changed to this:

**After:**

```cpp
#include "google/cloud/bigquery/storage/v1/bigquery_read_client.h"
```

</details>

### Bigquery

<details>
<summary>Removed <code>bigquery/retry_traits.h</code> file</summary>

The library no longer exposes the `google/cloud/bigquery/retry_traits.h` header
file. It only contained internal symbols.

</details>

### Bigtable

<details>
<summary>Removed <code>bigtable::RowReader</code> constructors
</summary>

We have removed the `bigtable::RowReader` constructors that accept `DataClient`
as an argument.

Developers that read rows by directly constructing a `RowReader` object should
instead construct a `Table` object and call `Table::ReadRows(...)`.

For example, code that used to look like this:

**Before:**

```cpp
#include "google/cloud/bigtable/data_client.h"
#include "google/cloud/bigtable/row_reader.h"
#include "google/cloud/bigtable/table.h"

// ...

auto client = google::cloud::bigtable::MakeDataClient(
    "my-project", "my-instance", creds);
auto reader = google::cloud::bigtable::RowReader(
    client, "my-table-id", google::cloud::bigtable::RowSet("r1", "r2"),
    google::cloud::bigtable::RowReader::NO_ROWS_LIMIT,
    google::cloud::bigtable::Filter::PassAllFilter(),
    /*...retry and backoff policies...*/);

for (auto& row : reader) {
  if (!row) throw std::move(row).status();
  // ...
}
```

Should be changed to this:

**After:**

```cpp
#include "google/cloud/bigtable/table.h"

// ...

namespace cbt = google::cloud::bigtable;
cbt::Table table(cbt::MakeDataConnection(),
                 cbt::TableResource("my-project", "my-instance", "my-table-id"));

for (auto& row : table.ReadRows(
         cbt::RowSet("r1", "r2"),
         cbt::Filter::PassAllFilter())) {
  if (!row) throw std::move(row).status();
  // ...
}
```

</details>

<details>
  <summary>Removed <code>bigtable::ClientOptions</code>
</summary>
#### `bigtable::ClientOptions`

We have removed the deprecated `bigtable::ClientOptions` class. Please use
`google::cloud::Options` instead.

The following table shows the mapping from `bigtable::ClientOptions` methods to
their `google::cloud::Options` equivalents:

| `bigtable::ClientOptions` method    | `google::cloud::Options` equivalent                                                             |
| ----------------------------------- | ----------------------------------------------------------------------------------------------- |
| `(constructor)`                     | `google::cloud::Options{}`                                                                      |
| `set_data_endpoint`                 | `google::cloud::EndpointOption`                                                                 |
| `set_admin_endpoint`                | `google::cloud::EndpointOption`                                                                 |
| `set_connection_pool_name`          | `google::cloud::GrpcChannelArgumentsOption` or`google::cloud::GrpcChannelArgumentsNativeOption` |
| `set_connection_pool_size`          | `google::cloud::GrpcNumChannelsOption`                                                          |
| `SetCredentials`                    | `google::cloud::GrpcCredentialOption`                                                           |
| `set_channel_arguments`             | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetCompressionAlgorithm`           | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetGrpclbFallbackTimeout`          | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetUserAgentPrefix`                | `google::cloud::UserAgentProductsOption` or`google::cloud::GrpcChannelArgumentsNativeOption`    |
| `SetResourceQuota`                  | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetMaxReceiveMessageSize`          | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetMaxSendMessageSize`             | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetLoadBalancingPolicyName`        | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetServiceConfigJSON`              | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `SetSslTargetNameOverride`          | `google::cloud::GrpcChannelArgumentsNativeOption`                                               |
| `enable_tracing`, `disable_tracing` | `google::cloud::LoggingComponentsOption`                                                        |
| `tracing_options`                   | `google::cloud::GrpcTracingOptionsOption`                                                       |
| `set_max_conn_refresh_period`       | `bigtable::MaxConnectionRefreshOption`                                                          |
| `set_min_conn_refresh_period`       | `bigtable::MinConnectionRefreshOption`                                                          |
| `set_background_thread_pool_size`   | `google::cloud::GrpcBackgroundThreadPoolSizeOption`                                             |
| `DisableBackgroundThreads`          | `google::cloud::GrpcCompletionQueueOption`                                                      |

Example usage of the replacements can be found below.

**Before:**

```cpp
auto client = bigtable::Client(
    bigtable::ClientOptions().set_connection_pool_size(4));
```

**After:**

```cpp
auto client = bigtable::Client(
    google::cloud::Options{}.set<google::cloud::GrpcNumChannelsOption>(4));
```

#### `bigtable::CreateDefaultDataClient`

We have removed the deprecated `bigtable::CreateDefaultDataClient` function.
Please use `bigtable::MakeDataClient` instead.

**Before:**

```cpp
auto client = bigtable::CreateDefaultDataClient(
    "my-project", "my-instance",
    bigtable::ClientOptions().set_connection_pool_size(4));
```

**After:**

```cpp
auto client = bigtable::MakeDataClient(
    "my-project", "my-instance",
    google::cloud::Options{}.set<google::cloud::GrpcNumChannelsOption>(4));
```

#### `bigtable::CreateDefaultAdminClient`

The deprecated `bigtable::CreateDefaultAdminClient` function has been removed.
Please use `bigtable::MakeAdminClient` instead.

**Before:**

```cpp
auto client = bigtable::CreateDefaultAdminClient(
    "my-project", bigtable::ClientOptions().set_connection_pool_size(4));
```

**After:**

```cpp
auto client = bigtable::MakeAdminClient(
    "my-project",
    google::cloud::Options{}.set<google::cloud::GrpcNumChannelsOption>(4));
```

#### `bigtable::CreateDefaultInstanceAdminClient`

The deprecated `bigtable::CreateDefaultInstanceAdminClient` function has been
removed. Please use `bigtable::MakeInstanceAdminClient` instead.

**Before:**

```cpp
auto client = bigtable::CreateDefaultInstanceAdminClient(
    "my-project", bigtable::ClientOptions().set_connection_pool_size(4));
```

**After:**

```cpp
auto client = bigtable::MakeInstanceAdminClient(
    "my-project",
    google::cloud::Options{}.set<google::cloud::GrpcNumChannelsOption>(4));
```

</details>

<details>

<summary>Removed <code>bigtable::AsyncRowReader<>::NO_ROWS_LIMIT</code>
</summary>

AsyncRowReader::NO_ROWS_LIMIT has been removed. Please use
`google::cloud::bigtable::RowReader::NO_ROWS_LIMIT` instead.

```cpp
// Before
auto limit = google::cloud::bigtable::AsyncRowReader<>::NO_ROWS_LIMIT;

// After
auto limit = google::cloud::bigtable::RowReader::NO_ROWS_LIMIT;
```

</details>

<details>
<summary>Removed Endpoint Options
</summary>

We have removed the `bigtable::DataEndpointOption`,
`bigtable::AdminEndpointOption`, and `bigtable::InstanceAdminEndpointOption`
classes. Applications should use `google::cloud::EndpointOption` instead.

**Before:**

```cpp
auto options = google::cloud::Options{}.set<google::cloud::bigtable::DataEndpointOption>("...");
```

**After:**

```cpp
auto options = google::cloud::Options{}.set<google::cloud::EndpointOption>("...");
```

</details>

<details>
<summary>Removed <code>bigtable::DataClient</code> and related functions</summary>

We have removed the `bigtable::DataClient` class and its associated factory
functions (e.g., `MakeDataClient`). Applications should now use
`bigtable::DataConnection` and `bigtable::MakeDataConnection()` instead. For
detailed migration steps and examples, please refer to the migration guide:

[Migrating from DataClient to DataConnection](https://docs.cloud.google.com/cpp/docs/reference/bigtable/latest/migrating-from-dataclient)

</details>

<details>
<summary>Removed <code>bigtable::MetadataUpdatePolicy</code></summary>

We have removed the `bigtable::MetadataUpdatePolicy` class. It was only used in
internal legacy files.

</details>

<details>
<summary>Removed <code>bigtable::AdminClient</code> and <code>bigtable::TableAdmin</code></summary>

We have replaced the `bigtable::AdminClient` class and `bigtable::TableAdmin`
class with `bigtable_admin::BigtableTableAdminClient`.

**Before:**

```cpp

std::shared_ptr<bigtable::AdminClient> admin_client = 
    bigtable::MakeAdminClient("project-id");
auto table_admin = std::make_unique<bigtable::TableAdmin>(
    admin_client, "instance-id");

// Drop a selection of rows by key prefix.
auto result = table_admin.DropRowByPrefix("table-id", "row-key-prefix");

// Drop all rows.
result = table_admin.DropAllRows("table-id");
```

**After:**

```cpp
#include "google/cloud/bigtable/admin/bigtable_table_admin_client.h"

auto table_admin = bigtable_admin::BigtableTableAdminClient(
    bigtable_admin::MakeBigtableAdminConnection());
auto table_name = bigtable::TableName("project-id", "instance-id", "table-id");

// Drop a selection of rows by key prefix.
google::bigtable::admin::v2::DropRowRangeRequest drop_rows_by_prefix;
drop_rows_by_prefix.set_name(table_name);
drop_rows_by_prefix.set_row_key_prefix("row-key-prefix");
auto result = table_admin.DropRowRange(drop_rows_by_prefix);

// Drop all rows.
google::bigtable::admin::v2::DropRowRangeRequest drop_all_rows;
drop_all_rows.set_name(table_name);
drop_all_rows.set_delete_all_data_from_table(true);
result = table_admin.DropRowRange(drop_all_rows);
```

</details>

<details><summary><code>WaitForConsistency</code> is now a free function</summary>

With the removal of the `bigtable::TableAdmin` class, we have moved
`WaitForConsistency` to
`bigtable_admin::BigtableTableAdminClient::WaitForConsistency`.

**Before:**

```cpp

std::shared_ptr<bigtable::AdminClient> admin_client = 
    bigtable::MakeAdminClient("project-id");
auto table_admin = std::make_unique<bigtable::TableAdmin>(
    admin_client, "instance-id");

auto token = table_admin.GenerateConsistencyToken("table-id");
if (!token) throw std::runtime_error(token.status().message());
auto result = table_admin.WaitForConsistency("table-id", *token);
```

**After:**

```cpp
#include "google/cloud/bigtable/admin/bigtable_table_admin_client.h"

auto connection = bigtable_admin::MakeBigtableAdminConnection();
auto table_admin = bigtable_admin::BigtableTableAdminClient(connection);
auto table_name = bigtable::TableName("project-id", "instance-id", "table-id");

auto token = table_admin.GenerateConsistencyToken(table_name);
if (!token) throw std::runtime_error(token.status().message());

google::bigtable::admin::v2::CheckConsistencyRequest wait_request;
wait_request.set_name(table_name);
wait_request.set_consistency_token(token->consistency_token());
auto wait_response = table_admin.WaitForConsistency(wait_request).get();
```

</details>

<details>
<summary>Removed <code>bigtable::InstanceAdminClient</code> and <code>bigtable::InstanceAdmin</code></summary>

We have replaced the `bigtable::InstanceAdminClient` class and
`bigtable::InstanceAdmin` class with
`bigtable_admin::BigtableInstanceAdminClient`.

**Before:**

```cpp
auto instance_admin_client = bigtable::MakeInstanceAdminClient("project-id");
auto instance_admin =
    std::make_unique<bigtable::InstanceAdmin>(instance_admin_client);

auto clusters = instance_admin->ListClusters();
```

**After:**

```cpp
#include "google/cloud/bigtable/admin/bigtable_instance_admin_client.h"

auto instance_admin =
        std::make_unique<bigtable_admin::BigtableInstanceAdminClient>(
            bigtable_admin::MakeBigtableInstanceAdminConnection());

auto clusters = instance_admin->ListClusters(
    InstanceName("project-id", "instance-id"));
```

</details>

### IAM

<details>

<summary>Removed <code>iam/retry_traits.h</code> file</summary>

The library no longer exposes `google/cloud/iam/retry_traits.h` header file. It
only contained internal symbols.

</details>

### Pubsub

<details>
  <summary>Removed <code>pubsub::PublisherOptions</code>
</summary>
#### `pubsub::PublisherOptions`

We have removed the deprecated `pubsub::PublisherOptions`. Please use
`google::cloud::Options` instead.

The following table shows the mapping from `pubsub::PublisherOptions` methods to
their `google::cloud::Options` equivalents:

| `pubsub::PublisherOptions` method | `google::cloud::Options` equivalent                |
| --------------------------------- | -------------------------------------------------- |
| `(constructor)`                   | `google::cloud::Options{}`                         |
| `set_maximum_hold_time`           | `google::cloud::pubsub::MaxHoldTimeOption`         |
| `set_maximum_batch_message_count` | `google::cloud::pubsub::MaxBatchMessagesOption`    |
| `set_maximum_batch_bytes`         | `google::cloud::pubsub::MaxBatchBytesOption`       |
| `enable_message_ordering`         | `google::cloud::pubsub::MessageOrderingOption`     |
| `disable_message_ordering`        | `google::cloud::pubsub::MessageOrderingOption`     |
| `set_maximum_pending_bytes`       | `google::cloud::pubsub::MaxPendingBytesOption`     |
| `set_maximum_pending_messages`    | `google::cloud::pubsub::MaxPendingMessagesOption`  |
| `set_full_publisher_ignored`      | `google::cloud::pubsub::FullPublisherActionOption` |
| `set_full_publisher_rejects`      | `google::cloud::pubsub::FullPublisherActionOption` |
| `set_full_publisher_blocks`       | `google::cloud::pubsub::FullPublisherActionOption` |

Example usage of the replacements can be found below.

**Before:**

```cpp
namespace gc = ::google::cloud;
namespace pubsub = ::google::cloud::pubsub;

auto publisher_options = pubsub::PublisherOptions{}
    .enable_message_ordering()
    .set_full_publisher_ignored();

auto publisher = pubsub::Publisher(pubsub::MakePublisherConnection(
    topic, publisher_options);
```

**After:**

```cpp
namespace gc = ::google::cloud;
namespace pubsub = ::google::cloud::pubsub;

auto options = gc::Options{}
    .set<pubsub::MessageOrderingOption>(true)
    .set<pubsub::FullPublisherActionOption>(
        pubsub::FullPublisherAction::kIgnored);

auto publisher = pubsub::Publisher(pubsub::MakePublisherConnection(
    topic, options));
```

</details>

<details>
  <summary>Removed <code>pubsub::SubscriberOptions</code>
</summary>
#### `pubsub::SubscriberOptions`

We have removed the deprecated `pubsub::SubscriberOptions`. Please use
`google::cloud::Options` instead.

The following table shows the mapping from `pubsub::SubscriberOptions` methods
to their `google::cloud::Options` equivalents:

| `pubsub::SubscriberOptions` method | `google::cloud::Options` equivalent                   |
| ---------------------------------- | ----------------------------------------------------- |
| `(constructor)`                    | `google::cloud::Options{}`                            |
| `set_max_deadline_time`            | `google::cloud::pubsub::MaxDeadlineTimeOption`        |
| `set_max_deadline_extension`       | `google::cloud::pubsub::MaxDeadlineExtensionOption`   |
| `set_max_outstanding_messages`     | `google::cloud::pubsub::MaxOutstandingMessagesOption` |
| `set_max_outstanding_bytes`        | `google::cloud::pubsub::MaxOutstandingBytesOption`    |
| `set_max_concurrency`              | `google::cloud::pubsub::MaxConcurrencyOption`         |
| `set_shutdown_polling_period`      | `google::cloud::pubsub::ShutdownPollingPeriodOption`  |

Example usage of the replacements can be found below.

**Before:**

```cpp
namespace gc = ::google::cloud;
namespace pubsub = ::google::cloud::pubsub;

auto subscriber_options = pubsub::SubscriberOptions{}
    .set_max_deadline_time(std::chrono::seconds(10))
    .set_max_outstanding_messages(42);

auto subscriber = pubsub::Subscriber(pubsub::MakeSubscriberConnection(
    subscription, subscriber_options);
```

**After:**

```cpp
namespace gc = ::google::cloud;
namespace pubsub = ::google::cloud::pubsub;

auto options = gc::Options{}
    .set<pubsub::MaxDeadlineTimeOption>(std::chrono::seconds(10))
    .set<pubsub::MaxOutstandingMessagesOption>(42);

auto subscriber = pubsub::Subscriber(pubsub::MakeSubscriberConnection(
    subscription, options));
```

</details>

### Spanner

<details>
<summary>All sessions are now Multiplexed Sessions</summary>

The Spanner library now ignores all SessionPool related options, which are
marked as deprecated and will be removed in the future:

- `EnableMultiplexedSessionOption`
- `SessionPoolMinSessionsOption`
- `SessionPoolMaxSessionsPerChannelOption`
- `SessionPoolMaxIdleSessionsOption`
- `SessionPoolActionOnExhaustionOption`
- `SessionPoolKeepAliveIntervalOption`

</details>

<details>
<summary>Removed <code>spanner::MakeTestRow</code>
</summary>

We have removed the `spanner::MakeTestRow` functions. Please use
`spanner_mocks::MakeRow` instead.

**Before:**

```cpp
#include "google/cloud/spanner/row.h"

// ...

auto row = google::cloud::spanner::MakeTestRow(
    {{"c0", google::cloud::spanner::Value(42)}});
auto row2 = google::cloud::spanner::MakeTestRow(1, "foo", true);
```

**After:**

```cpp
#include "google/cloud/spanner/mocks/row.h"

// ...

auto row = google::cloud::spanner_mocks::MakeRow(
    {{"c0", google::cloud::spanner::Value(42)}});
auto row2 = google::cloud::spanner_mocks::MakeRow(1, "foo", true);
```

</details>

<details>
<summary>Removed <code>spanner::ClientOptions</code> class</summary>

We have removed the `spanner::ClientOptions` class. Use `google::cloud::Options`
instead to set the following as needed:

- `spanner::QueryOptimizerVersionOption`
- `spanner::QueryOptimizerStatisticsPackageOption`
- `spanner::RequestPriorityOption`
- `spanner::RequestTagOption`

**Before:**

```cpp
#include "google/cloud/spanner/client.h"

// ...

namespace spanner = ::google::cloud::spanner;
auto client_options = spanner::ClientOptions().set_query_options(
    spanner::QueryOptions().set_optimizer_version("1"));

auto client = spanner::Client(connection, client_options);
```

**After:**

```cpp
#include "google/cloud/spanner/client.h"
#include "google/cloud/spanner/options.h"

// ...

namespace spanner = ::google::cloud::spanner;
auto options = google::cloud::Options{}.set<spanner::QueryOptimizerVersionOption>("1");

auto client = spanner::Client(connection, options);
```

</details>

<details>

<summary>Removed <code>admin/retry_traits.h</code> file</summary>

The library no longer exposes `google/cloud/spanner/admin/retry_traits.h` header
file. It only contained internal symbols.

</details>

<details>
<summary>Removed Admin Clients from <code>spanner</code> namespace</summary>

We have removed the `DatabaseAdminClient` and `InstanceAdminClient` classes (and
their associated connection classes and factory functions) from the
`google::cloud::spanner` namespace. Please use the replacements in
`google::cloud::spanner_admin`.

**Before:**

```cpp
#include "google/cloud/spanner/database_admin_client.h"
#include "google/cloud/spanner/instance_admin_client.h"

namespace spanner = ::google::cloud::spanner;

void Function(spanner::DatabaseAdminClient db_admin,
              spanner::InstanceAdminClient in_admin) {
  // ...
}
```

**After:**

```cpp
#include "google/cloud/spanner/admin/database_admin_client.h"
#include "google/cloud/spanner/admin/instance_admin_client.h"

namespace spanner_admin = ::google::cloud::spanner_admin;

void Function(spanner_admin::DatabaseAdminClient db_admin,
              spanner_admin::InstanceAdminClient in_admin) {
  // ...
}
```

</details>

### Storage

<details>
<summary><code>ClientOptions</code> is removed</summary>

The `ClientOptions` class is no longer available. You should now use
`google::cloud::Options` to configure the `Client`.

**Before:**

```cpp
#include "google/cloud/storage/client.h"

void CreateClient() {
  auto credentials = google::cloud::storage::oauth2::GoogleDefaultCredentials().value();
  auto options = google::cloud::storage::ClientOptions(credentials);
  options.set_project_id("my-project");
  options.set_upload_buffer_size(1024 * 1024);

  google::cloud::storage::Client client(options);
}
```

**After:**

```cpp
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/options.h" // For option structs

void CreateClient() {
  auto credentials = google::cloud::MakeGoogleDefaultCredentials();
  auto client = google::cloud::storage::Client(
      google::cloud::Options{}
          .set<google::cloud::Oauth2CredentialsOption>(credentials)
          .set<google::cloud::storage::ProjectIdOption>("my-project")
          .set<google::cloud::storage::UploadBufferSizeOption>(1024 * 1024));
}
```

Use the following table to map `ClientOptions` setters to
`google::cloud::Options`:

| `ClientOptions` Method                | Replacement Option (`.set<T>(value)`)                   |
| :------------------------------------ | :------------------------------------------------------ |
| `set_credentials(c)`                  | `google::cloud::storage::Oauth2CredentialsOption`       |
| `set_project_id(p)`                   | `google::cloud::storage::ProjectIdOption`               |
| `set_endpoint(url)`                   | `google::cloud::storage::RestEndpointOption`            |
| `set_iam_endpoint(url)`               | `google::cloud::storage::IamEndpointOption`             |
| `SetDownloadBufferSize`               | `google::cloud::storage::DownloadBufferSizeOption`      |
| `SetUploadBufferSizee`                | `google::cloud::storage::UploadBufferSizeOption`        |
| `set_maximum_simple_upload_size(s)`   | `google::cloud::storage::MaximumSimpleUploadSizeOption` |
| `set_enable_http_tracing(true)`       | `google::cloud::LoggingComponentsOption`                |
| `set_enable_raw_client_tracing(true)` | `google::cloud::LoggingComponentsOption`                |

**Example for Tracing:**

```cpp
// Before
options.set_enable_http_tracing(true);

// After
auto opts = Options{}.lookup<LoggingComponentsOption>().insert("raw-client");
```

</details>

<details>
<summary><code>ChannelOptions</code> is removed</summary>

The `ChannelOptions` class is no longer available. You should now use
`google::cloud::Options` to configure the transport channel.

**Before:**

```cpp
#include "google/cloud/storage/grpc_plugin.h"

void CreateClient() {
  auto options = google::cloud::storage::ChannelOptions()
      .set_ssl_root_path("path/to/roots.pem");

  auto client = google::cloud::storage::MakeGrpcClient(
      google::cloud::storage::ClientOptions(), options);
}
```

**After:**

```cpp
#include "google/cloud/storage/grpc_plugin.h"
#include "google/cloud/grpc_options.h"
#include "google/cloud/common_options.h"

void CreateClient() {
  auto client = google::cloud::storage::MakeGrpcClient(
      google::cloud::Options{}.set<google::cloud::CARootsFilePathOption>(
          "path/to/roots.pem"));
}
```

</details>

<details>
<summary>ChannelOptions Mapping</summary>

Use the following table to map `ChannelOptions` setters to
`google::cloud::Options`:

| `ChannelOptions` Method | Replacement Option (`.set<T>(value)`)  |
| :---------------------- | :------------------------------------- |
| `set_ssl_root_path(p)`  | `google::cloud::CARootsFilePathOption` |

</details>

<details>
<summary><code>Client</code> Constructor removal</summary>

We have removed the `Client(ClientOptions)` constructor. The default constructor
`Client()` generally uses default options and default credentials. To customize,
use `Client(Options)`.

**Before:**

```cpp
#include "google/cloud/storage/client.h"

void CreateClient() {
  auto credentials = google::cloud::storage::oauth2::GoogleDefaultCredentials().value();
  auto options = google::cloud::storage::ClientOptions(credentials);
  auto client = google::cloud::storage::Client(options);
}
```

**After:**

```cpp
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/options.h"

void CreateClient() {
  auto credentials = google::cloud::MakeGoogleDefaultCredentials();
  auto client = google::cloud::storage::Client(
      google::cloud::Options{}.set<google::cloud::storage::Oauth2CredentialsOption>(credentials));
}
```

</details>

<details>
<summary>Removed <code>Client(Connection, NoDecorations)</code> constructor</summary>

We have removed the `Client` constructor that accepted a `StorageConnection` and
the `NoDecorations` tag. This was intended only for test code.

**Before:**

```cpp
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/testing/mock_storage_connection.h"

void TestClient() {
  auto mock = std::make_shared<google::cloud::storage::testing::MockStorageConnection>();
  // ...
  auto client = google::cloud::storage::Client(
      mock, google::cloud::storage::Client::NoDecorations{});
}
```

**After:**

```cpp
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/testing/mock_storage_connection.h"

void TestClient() {
  auto mock = std::make_shared<google::cloud::storage::testing::MockStorageConnection>();
  // ...
  auto client = google::cloud::storage::internal::ClientImplDetails::CreateWithoutDecorations(mock);
}
```

</details>

<details>
<summary>Removed <code>Client::raw_client()</code></summary>

We have removed the `Client::raw_client()` method. This was intended only for
internal use or testing. If you need access to the underlying connection for
testing purposes, use `google::cloud::storage::internal::ClientImplDetails`.

**Before:**

```cpp
#include "google/cloud/storage/client.h"

void UseRawClient(google::cloud::storage::Client client) {
  auto connection = client.raw_client();
}
```

**After:**

```cpp
#include "google/cloud/storage/client.h"

void UseRawClient(google::cloud::storage::Client client) {
  auto connection =
      google::cloud::storage::internal::ClientImplDetails::GetConnection(client);
}
```

</details>

<details>
<summary>Removed <code>storage_experimental::GrpcPluginOption</code> and <code>storage_experimental::DefaultGrpcClient</code></summary>

The `storage_experimental::GrpcPluginOption` is no longer necessary. Instead of
calling `storage_experimental::DefaultGrpcClient` now call
`storage::MakeGrpcClient`

**Before:**

```cpp
#include "google/cloud/storage/grpc_plugin.h"
namespace gc = ::google::cloud;

auto options = gc::Options{}
    .set<gc::storage_experimental::GrpcPluginOption>("media");
auto client = gc::storage_experimental::DefaultGrpcClient(options);
```

**After:**

```cpp
#include "google/cloud/storage/grpc_plugin.h"
namespace gc = ::google::cloud;

auto client = gc::storage::MakeGrpcClient();
```

</details>

<details>
<summary>Removed <code>experimental-storage_grpc</code> targets from CMake and Bazel</summary>

CMake should now link to `google-cloud-cpp::storage_grpc`.

Bazel should now depend on `@google_cloud_cpp//:storage_grpc`

</details>

<details>
<summary>Removed deprecated <code>Oauth2CredentialsOption</code></summary>

You should use the `google::cloud::UnifiedCredentialsOption` and the unified
credentials API documented at
https://docs.cloud.google.com/cpp/docs/reference/common/latest/group__guac
instead.

**Before:**

```cpp
#include "google/cloud/options.h"
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/oauth2/google_credentials.h"

namespace gc = ::google::cloud;
namespace gcs = ::google::cloud::storage;
namespace oauth2 = ::google::cloud::storage::oauth2;

auto options = gc::Options{}
    .set<gcs::Oauth2CredentialsOption>(oauth2::CreateAnonymousCredentials());
auto client = gcs::Client(options);
```

**After:**

```cpp
#include "google/cloud/options.h"
#include "google/cloud/storage/client.h"
#include "google/cloud/credentials.h"

namespace gc = ::google::cloud;
namespace gcs = ::google::cloud::storage;

auto options = gc::Options{}
    .set<gc::UnifiedCredentialsOption>(gc::MakeInsecureCredentials());
auto client = gcs::Client(options);
```

</details>

<details>
<summary>Removed deprecated <code>CreateServiceAccountCredentialsFromFilePath</code></summary>

You should use the `google::cloud::MakeServiceAccountCredentialsFromFile`
factory function and associated override options `google::cloud::ScopesOption`
and `google::cloud::subjectOption` instead.

**Before:**

```cpp
#include "google/cloud/options.h"
#include "google/cloud/storage/client.h"
#include "google/cloud/storage/oauth2/google_credentials.h"

namespace gc = ::google::cloud;
namespace gcs = ::google::cloud::storage;
namespace oauth2 = ::google::cloud::storage::oauth2;

std::set<std::string> scopes = {"scope1", "scope2"};
auto credentials = CreateServiceAccountCredentialsFromFilePath(
    "path-to-file", scopes, "my-subject");

auto options = gc::Options{}
    .set<gcs::Oauth2CredentialsOption>(credentials);
auto client = gcs::Client(options);
```

**After:**

```cpp
#include "google/cloud/options.h"
#include "google/cloud/storage/client.h"
#include "google/cloud/credentials.h"

namespace gc = ::google::cloud;
namespace gcs = ::google::cloud::storage;

auto options = gc::Options{}
    .set<gc::ScopesOption>(std::vector<std::string>({"scope1", "scope2"}))
    .set<gc::SubjectOption>("my-subject");

options = options.set<gc::UnifiedCredentialsOption>(
    gc::MakeServiceAccountCredentialsFromFile("path-to-file", options));
auto client = gcs::Client(options);
```

</details>
