diff --git a/sdk/tables/assets.json b/sdk/tables/assets.json index 8d744db5e..fba221a28 100644 --- a/sdk/tables/assets.json +++ b/sdk/tables/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "cpp", "TagPrefix": "cpp/tables", - "Tag": "cpp/tables_cb42be8953" + "Tag": "cpp/tables_0b3363cab7" } diff --git a/sdk/tables/azure-data-tables/README.md b/sdk/tables/azure-data-tables/README.md index bdf2627f0..375975fdf 100644 --- a/sdk/tables/azure-data-tables/README.md +++ b/sdk/tables/azure-data-tables/README.md @@ -105,7 +105,7 @@ Two different clients are provided to interact with the various components of th ##### Creating and deleting a table -In order to Create/Delete a table we need to create a TablesClient first. +In order to Create/Delete a table we need to create a `TableServiceClient` first. ```cpp #include @@ -113,7 +113,8 @@ In order to Create/Delete a table we need to create a TablesClient first. using namespace Azure::Data::Tables; const std::string TableName = "sample1"; ... -auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); +auto credential = std::make_shared(); +auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); // create new table tableServiceClient.CreateTable(TableName); @@ -155,7 +156,7 @@ auto tableClient = tableServiceClient.GetTableClient(TableName); ``` N.B. Here we are obtaining the table client from the table service client using the credentials that were passed to the table service client. -##### Create a client with a connection string +##### Create a client with DefaultAzureCredentials In order to Create/Update/Merge/Delete entities we need to create a TablesClient first. ```cpp @@ -164,7 +165,8 @@ In order to Create/Update/Merge/Delete entities we need to create a TablesClient using namespace Azure::Data::Tables; const std::string TableName = "sample1"; ... -auto tableClient = TableClient::CreateFromConnectionString(..., TableName); +auto credential = std::make_shared(); +auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); ``` ##### Entities diff --git a/sdk/tables/azure-data-tables/inc/azure/data/tables/account_sas_builder.hpp b/sdk/tables/azure-data-tables/inc/azure/data/tables/account_sas_builder.hpp index 2b8b1761b..0fa3706f2 100644 --- a/sdk/tables/azure-data-tables/inc/azure/data/tables/account_sas_builder.hpp +++ b/sdk/tables/azure-data-tables/inc/azure/data/tables/account_sas_builder.hpp @@ -106,15 +106,15 @@ namespace Azure { namespace Data { namespace Tables { namespace Sas { */ Delete = 4, - /** - * @brief Indicates that Add is permitted. - */ - Add = 8, - /** * @brief Indicates that List is permitted. */ - List = 16, + List = 8, + + /** + * @brief Indicates that Add is permitted. + */ + Add = 16, /** * @brief Indicates that Update is permitted. diff --git a/sdk/tables/azure-data-tables/inc/azure/data/tables/table_client.hpp b/sdk/tables/azure-data-tables/inc/azure/data/tables/table_client.hpp index 4b6830c43..bf0967f19 100644 --- a/sdk/tables/azure-data-tables/inc/azure/data/tables/table_client.hpp +++ b/sdk/tables/azure-data-tables/inc/azure/data/tables/table_client.hpp @@ -88,21 +88,6 @@ namespace Azure { namespace Data { namespace Tables { std::shared_ptr credential, const TableClientOptions& options = {}); - /** - * @brief Initializes a new instance of tableClient. - * - * @param tableName The name of the table. - * @param credential The named key credential used to sign requests. - * @param url A url referencing the table that includes the name of the account and the name of - * @param options Optional client options that define the transport pipeline policies for - * authentication, retries, etc., that are applied to every request. - */ - explicit TableClient( - const std::string& tableName, - std::shared_ptr credential, - std::string url, - const TableClientOptions& options = {}); - /** * @brief Initializes a new instance of tableClient. * @@ -118,41 +103,6 @@ namespace Azure { namespace Data { namespace Tables { const std::string& tableName, const TableClientOptions& options = {}); - /** - * @brief Initializes a new instance of tableClient. - * - * @param connectionString the connection string used to initialize. - * @param tableName The name of the table. - * @param options Optional client options that define the transport pipeline policies for - * authentication, retries, etc., that are applied to every request. - * @return TableClient. - */ - static TableClient CreateFromConnectionString( - const std::string& connectionString, - const std::string& tableName, - const TableClientOptions& options = {}); - - /** - * @brief Retrieves details about any stored access policies specified on the table that may be - * used with Shared Access Signatures. - * - * @param context for canceling long running operations. - * @return Get access policy result. - */ - Response GetAccessPolicy(Core::Context const& context = {}); - - /** - * @brief Sets stored access policies for the table that may be used with Shared Access - * Signatures. - * - * @param tableAccessPolicy The TableAccessPolicy to set. - * @param context for canceling long running operations. - * @return Set access policy result. - */ - Response SetAccessPolicy( - Models::TableAccessPolicy const& tableAccessPolicy, - Core::Context const& context = {}); - /** * @brief Add entity in a table. * @@ -236,14 +186,14 @@ namespace Azure { namespace Data { namespace Tables { * @return Table entity. */ Response GetEntity( - const std::string& partitionKey, - const std::string& rowKey, + std::string const& partitionKey, + std::string const& rowKey, Core::Context const& context = {}); /** * @brief Submits a transaction. * - * @param steps the transaction steps to execute. + * @param steps The transaction steps to execute. * @param context for canceling long running operations. * @return Submit transaction result. */ diff --git a/sdk/tables/azure-data-tables/inc/azure/data/tables/table_service_client.hpp b/sdk/tables/azure-data-tables/inc/azure/data/tables/table_service_client.hpp index 8b11c5e85..6fb8c759c 100644 --- a/sdk/tables/azure-data-tables/inc/azure/data/tables/table_service_client.hpp +++ b/sdk/tables/azure-data-tables/inc/azure/data/tables/table_service_client.hpp @@ -50,20 +50,6 @@ namespace Azure { namespace Data { namespace Tables { std::shared_ptr credential, const TableClientOptions& options = {}); - /** - * @brief Initializes a new instance of tableClient. - * - * @param serviceUrl A url referencing the table that includes the name of the account and the - * name of the table. - * @param credential The named key credential used to sign requests. - * @param options Optional client options that define the transport pipeline policies for - * authentication, retries, etc., that are applied to every request. - */ - explicit TableServiceClient( - const std::string& serviceUrl, - std::shared_ptr credential, - const TableClientOptions& options = {}); - /** * @brief Initializes a new instance of tableClient. * @@ -78,18 +64,6 @@ namespace Azure { namespace Data { namespace Tables { std::shared_ptr credential, const TableClientOptions& options = {}); - /** - * @brief Initializes a new instance of tableClient. - * - * @param connectionString the connection string used to initialize. - * @param options Optional client options that define the transport pipeline policies for - * authentication, retries, etc., that are applied to every request. - * @return TableServiceClient. - */ - static TableServiceClient CreateFromConnectionString( - const std::string& connectionString, - const TableClientOptions& options = {}); - /** * @brief Creates a new table under the given account. * @@ -176,7 +150,6 @@ namespace Azure { namespace Data { namespace Tables { private: std::shared_ptr m_pipeline; std::shared_ptr m_tokenCredential; - std::shared_ptr m_namedKeyCredential; Core::Url m_url; }; }}} // namespace Azure::Data::Tables diff --git a/sdk/tables/azure-data-tables/samples/CMakeLists.txt b/sdk/tables/azure-data-tables/samples/CMakeLists.txt index fa57f77a1..097ac99b4 100644 --- a/sdk/tables/azure-data-tables/samples/CMakeLists.txt +++ b/sdk/tables/azure-data-tables/samples/CMakeLists.txt @@ -8,26 +8,26 @@ if(MSVC) endif() add_executable(tables-getting-started tables_getting_started.cpp ) -target_link_libraries(tables-getting-started PRIVATE azure-data-tables get-env-helper) +target_link_libraries(tables-getting-started PRIVATE azure-data-tables azure-identity get-env-helper) create_per_service_target_build_for_sample(tables tables-getting-started) target_compile_definitions(tables-getting-started PRIVATE _azure_BUILDING_SAMPLES) add_executable(tables_entity_operations tables_entity_operations.cpp) -target_link_libraries(tables_entity_operations PRIVATE azure-data-tables get-env-helper) +target_link_libraries(tables_entity_operations PRIVATE azure-data-tables azure-identity get-env-helper) create_per_service_target_build_for_sample(tables tables_entity_operations) target_compile_definitions(tables_entity_operations PRIVATE _azure_BUILDING_SAMPLES) add_executable(tables_service_operations tables_service_operations.cpp) -target_link_libraries(tables_service_operations PRIVATE azure-data-tables get-env-helper) +target_link_libraries(tables_service_operations PRIVATE azure-data-tables azure-identity get-env-helper) create_per_service_target_build_for_sample(tables tables_service_operations) target_compile_definitions(tables_service_operations PRIVATE _azure_BUILDING_SAMPLES) add_executable(tables_transactions_ok tables_transactions_ok.cpp) -target_link_libraries(tables_transactions_ok PRIVATE azure-data-tables get-env-helper) +target_link_libraries(tables_transactions_ok PRIVATE azure-data-tables azure-identity get-env-helper) create_per_service_target_build_for_sample(tables tables_transactions_ok) target_compile_definitions(tables_transactions_ok PRIVATE _azure_BUILDING_SAMPLES) add_executable(tables_transactions_fail tables_transactions_fail.cpp) -target_link_libraries(tables_transactions_fail PRIVATE azure-data-tables get-env-helper) +target_link_libraries(tables_transactions_fail PRIVATE azure-data-tables azure-identity get-env-helper) create_per_service_target_build_for_sample(tables tables_transactions_fail) target_compile_definitions(tables_transactions_fail PRIVATE _azure_BUILDING_SAMPLES) diff --git a/sdk/tables/azure-data-tables/samples/tables_entity_operations.cpp b/sdk/tables/azure-data-tables/samples/tables_entity_operations.cpp index 9a3b362c6..c84720a4c 100644 --- a/sdk/tables/azure-data-tables/samples/tables_entity_operations.cpp +++ b/sdk/tables/azure-data-tables/samples/tables_entity_operations.cpp @@ -2,36 +2,28 @@ // Licensed under the MIT License. #include +#include #include #include #include #include -using namespace Azure::Data::Tables; -using namespace Azure::Data::Tables::Models; const std::string TableName = "table"; -std::string GetConnectionString() +// The following environment variables must be set before running the sample. +// * ACCOUNT_NAME: The name of the storage account. +std::string GetAccountName() { return std::getenv("ACCOUNT_NAME"); } +std::string const GetServiceUrl() { - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = std::getenv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); + return std::string{"https://" + GetAccountName() + ".table.core.windows.net/"}; } int main() { - auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); - auto tableClient = TableClient::CreateFromConnectionString(GetConnectionString(), TableName); + auto credential = std::make_shared(); + auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); + auto tableClient = Azure::Data::Tables::TableClient(GetServiceUrl(), TableName, credential); // create new table tableServiceClient.CreateTable(TableName); @@ -46,19 +38,19 @@ int main() Azure::Data::Tables::Models::TableEntity entity; entity.SetPartitionKey("P1"); entity.SetRowKey("R1"); - entity.Properties["Name"] = TableEntityProperty("Azure"); - entity.Properties["Product"] = TableEntityProperty("Tables"); + entity.Properties["Name"] = Azure::Data::Tables::Models::TableEntityProperty("Azure"); + entity.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables"); // create new entity auto response = tableClient.AddEntity(entity); // update entity std::cout << response.Value.ETag << std::endl; - entity.Properties["Product"] = TableEntityProperty("Tables2"); + entity.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables2"); auto updateResponse = tableClient.UpdateEntity(entity); std::cout << updateResponse.Value.ETag << std::endl; // merge entity - entity.Properties["Product"] = TableEntityProperty("Tables3"); + entity.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables3"); entity.SetETag(updateResponse.Value.ETag); auto updateResponse2 = tableClient.MergeEntity(entity); diff --git a/sdk/tables/azure-data-tables/samples/tables_getting_started.cpp b/sdk/tables/azure-data-tables/samples/tables_getting_started.cpp index 0cdf93765..e67c39673 100644 --- a/sdk/tables/azure-data-tables/samples/tables_getting_started.cpp +++ b/sdk/tables/azure-data-tables/samples/tables_getting_started.cpp @@ -2,34 +2,26 @@ // Licensed under the MIT License. #include +#include #include #include #include #include -std::string GetConnectionString() -{ - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = std::getenv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); -} - -using namespace Azure::Data::Tables; const std::string TableName = "sample1"; +// The following environment variables must be set before running the sample. +// * ACCOUNT_NAME: The name of the storage account. +std::string GetAccountName() { return std::getenv("ACCOUNT_NAME"); } +std::string const GetServiceUrl() +{ + return std::string{"https://" + GetAccountName() + ".table.core.windows.net/"}; +} int main() { - auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); + auto credential = std::make_shared(); + auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); // create new table tableServiceClient.CreateTable(TableName); diff --git a/sdk/tables/azure-data-tables/samples/tables_service_operations.cpp b/sdk/tables/azure-data-tables/samples/tables_service_operations.cpp index ca72dcad2..2019ac524 100644 --- a/sdk/tables/azure-data-tables/samples/tables_service_operations.cpp +++ b/sdk/tables/azure-data-tables/samples/tables_service_operations.cpp @@ -2,35 +2,27 @@ // Licensed under the MIT License. #include +#include #include #include #include #include -std::string GetConnectionString() -{ - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = std::getenv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); -} - -using namespace Azure::Data::Tables; const std::string TableName = "sample1"; +// The following environment variables must be set before running the sample. +// * ACCOUNT_NAME: The name of the storage account. +std::string GetAccountName() { return std::getenv("ACCOUNT_NAME"); } +std::string const GetServiceUrl() +{ + return std::string{"https://" + GetAccountName() + ".table.core.windows.net/"}; +} + int main() { - auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); - + auto credential = std::make_shared(); + auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); // query tables auto tables = tableServiceClient.QueryTables(); diff --git a/sdk/tables/azure-data-tables/samples/tables_transactions_fail.cpp b/sdk/tables/azure-data-tables/samples/tables_transactions_fail.cpp index 046c6fdb3..f61cd697d 100644 --- a/sdk/tables/azure-data-tables/samples/tables_transactions_fail.cpp +++ b/sdk/tables/azure-data-tables/samples/tables_transactions_fail.cpp @@ -2,58 +2,51 @@ // Licensed under the MIT License. #include +#include #include #include #include #include -using namespace Azure::Data::Tables; -using namespace Azure::Data::Tables::Models; - const std::string TableName = "transactions2"; -std::string GetConnectionString() +// The following environment variables must be set before running the sample. +// * ACCOUNT_NAME: The name of the storage account. +std::string GetAccountName() { return std::getenv("ACCOUNT_NAME"); } +std::string const GetServiceUrl() { - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = std::getenv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); + return std::string{"https://" + GetAccountName() + ".table.core.windows.net/"}; } int main() { - // Get the service client - auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); + auto credential = std::make_shared(); + auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); + // create table tableServiceClient.CreateTable(TableName); // get table client from table service client auto tableClient = tableServiceClient.GetTableClient(TableName); // Create two table entities - TableEntity entity; - TableEntity entity2; + Azure::Data::Tables::Models::TableEntity entity; + Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); entity.SetRowKey("R1"); - entity.Properties["Name"] = TableEntityProperty("Azure"); - entity.Properties["Product"] = TableEntityProperty("Tables"); + entity.Properties["Name"] = Azure::Data::Tables::Models::TableEntityProperty("Azure"); + entity.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables"); entity2.SetPartitionKey("P1"); entity2.SetRowKey("R1"); - entity2.Properties["Name"] = TableEntityProperty("Azure2"); - entity2.Properties["Product"] = TableEntityProperty("Tables2"); + entity2.Properties["Name"] = Azure::Data::Tables::Models::TableEntityProperty("Azure2"); + entity2.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables2"); // Create a transaction with two steps - std::vector steps; - steps.emplace_back(TransactionStep{TransactionActionType::Add, entity}); - steps.emplace_back(TransactionStep{TransactionActionType::Add, entity2}); + std::vector steps; + steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ + Azure::Data::Tables::Models::TransactionActionType::Add, entity}); + steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ + Azure::Data::Tables::Models::TransactionActionType::Add, entity2}); // Submit the transaction auto response = tableClient.SubmitTransaction(steps); diff --git a/sdk/tables/azure-data-tables/samples/tables_transactions_ok.cpp b/sdk/tables/azure-data-tables/samples/tables_transactions_ok.cpp index f8f0d97f2..4aeac1395 100644 --- a/sdk/tables/azure-data-tables/samples/tables_transactions_ok.cpp +++ b/sdk/tables/azure-data-tables/samples/tables_transactions_ok.cpp @@ -2,58 +2,50 @@ // Licensed under the MIT License. #include +#include #include #include #include #include -using namespace Azure::Data::Tables; -using namespace Azure::Data::Tables::Models; - const std::string TableName = "transactions"; -std::string GetConnectionString() +// The following environment variables must be set before running the sample. +// * ACCOUNT_NAME: The name of the storage account. +std::string GetAccountName() { return std::getenv("ACCOUNT_NAME"); } +std::string const GetServiceUrl() { - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = std::getenv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); + return std::string{"https://" + GetAccountName() + ".table.core.windows.net/"}; } int main() { - // Get the service client - auto tableServiceClient = TableServiceClient::CreateFromConnectionString(GetConnectionString()); - // create table + auto credential = std::make_shared(); + auto tableServiceClient = Azure::Data::Tables::TableServiceClient(GetServiceUrl(), credential); + tableServiceClient.CreateTable(TableName); // get table client from table service client auto tableClient = tableServiceClient.GetTableClient(TableName); // Create two table entities - TableEntity entity; - TableEntity entity2; + Azure::Data::Tables::Models::TableEntity entity; + Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); entity.SetRowKey("R1"); - entity.Properties["Name"] = TableEntityProperty("Azure"); - entity.Properties["Product"] = TableEntityProperty("Tables"); + entity.Properties["Name"] = Azure::Data::Tables::Models::TableEntityProperty("Azure"); + entity.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables"); entity2.SetPartitionKey("P1"); entity2.SetRowKey("R2"); - entity2.Properties["Name"] = TableEntityProperty("Azure2"); - entity2.Properties["Product"] = TableEntityProperty("Tables2"); + entity2.Properties["Name"] = Azure::Data::Tables::Models::TableEntityProperty("Azure2"); + entity2.Properties["Product"] = Azure::Data::Tables::Models::TableEntityProperty("Tables2"); // Create a transaction with two steps - std::vector steps; - steps.emplace_back(TransactionStep{TransactionActionType::Add, entity}); - steps.emplace_back(TransactionStep{TransactionActionType::Add, entity2}); + std::vector steps; + steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ + Azure::Data::Tables::Models::TransactionActionType::Add, entity}); + steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ + Azure::Data::Tables::Models::TransactionActionType::Add, entity2}); // Submit the transaction auto response = tableClient.SubmitTransaction(steps); diff --git a/sdk/tables/azure-data-tables/src/table_clients.cpp b/sdk/tables/azure-data-tables/src/table_clients.cpp index 7cde3655e..7187269cd 100644 --- a/sdk/tables/azure-data-tables/src/table_clients.cpp +++ b/sdk/tables/azure-data-tables/src/table_clients.cpp @@ -67,40 +67,6 @@ TableServiceClient::TableServiceClient( std::move(perOperationPolicies)); } -TableServiceClient::TableServiceClient( - const std::string& serviceUrl, - std::shared_ptr credential, - const TableClientOptions& options) - : m_url(Azure::Core::Url(serviceUrl)) -{ - m_namedKeyCredential = credential; - std::vector> perRetryPolicies; - std::vector> perOperationPolicies; - perRetryPolicies.emplace_back(std::make_unique()); - perOperationPolicies.emplace_back(std::make_unique(options.ApiVersion)); - m_pipeline = std::make_shared( - options, - _detail::TablesServicePackageName, - PackageVersion::ToString(), - std::move(perRetryPolicies), - std::move(perOperationPolicies)); - - TableClientOptions newOptions = options; - newOptions.PerRetryPolicies.emplace_back( - std::make_unique(credential)); - - std::vector> perRetryPolicies2; - std::vector> perOperationPolicies2; - perRetryPolicies2.emplace_back(std::make_unique()); - perOperationPolicies2.emplace_back(std::make_unique(newOptions.ApiVersion)); - m_pipeline = std::make_shared( - newOptions, - _detail::TablesServicePackageName, - PackageVersion::ToString(), - std::move(perRetryPolicies2), - std::move(perOperationPolicies2)); -} - TableServiceClient::TableServiceClient( const std::string& serviceUrl, std::shared_ptr credential, @@ -113,10 +79,6 @@ TableClient TableServiceClient::GetTableClient( const std::string& tableName, TableClientOptions const& options) const { - if (m_namedKeyCredential != nullptr) - { - return TableClient(tableName, m_namedKeyCredential, m_url.GetAbsoluteUrl(), options); - } if (m_tokenCredential != nullptr) { return TableClient(m_url.GetAbsoluteUrl(), tableName, m_tokenCredential, options); @@ -128,24 +90,6 @@ TableClient TableServiceClient::GetTableClient( throw std::runtime_error("TableServiceClient is not properly initialized."); } -TableServiceClient TableServiceClient::CreateFromConnectionString( - const std::string& connectionString, - const TableClientOptions& options) -{ - auto parsedConnectionString = ParseConnectionString(connectionString); - auto tablesUrl = std::move(parsedConnectionString.TableServiceUrl); - - if (parsedConnectionString.KeyCredential) - { - return TableServiceClient( - tablesUrl.GetAbsoluteUrl(), std::move(parsedConnectionString.KeyCredential), options); - } - else - { - return TableServiceClient(tablesUrl.GetAbsoluteUrl(), options); - } -} - Azure::Response TableServiceClient::PreflightCheck( Models::PreflightCheckOptions const& options, Core::Context const& context) @@ -349,41 +293,6 @@ TableClient::TableClient( std::move(perOperationPolicies)); } -TableClient::TableClient( - const std::string& tableName, - std::shared_ptr credential, - std::string url, - const TableClientOptions& options) - : m_url(std::move(url)), m_tableName(tableName) - -{ - std::vector> perRetryPolicies; - std::vector> perOperationPolicies; - perRetryPolicies.emplace_back(std::make_unique()); - perOperationPolicies.emplace_back(std::make_unique(options.ApiVersion)); - m_pipeline = std::make_shared( - options, - _detail::TablesServicePackageName, - PackageVersion::ToString(), - std::move(perRetryPolicies), - std::move(perOperationPolicies)); - - TableClientOptions newOptions = options; - newOptions.PerRetryPolicies.emplace_back( - std::make_unique(credential)); - - std::vector> perRetryPolicies2; - std::vector> perOperationPolicies2; - perRetryPolicies2.emplace_back(std::make_unique()); - perOperationPolicies2.emplace_back(std::make_unique(newOptions.ApiVersion)); - m_pipeline = std::make_shared( - newOptions, - _detail::TablesServicePackageName, - PackageVersion::ToString(), - std::move(perRetryPolicies2), - std::move(perOperationPolicies2)); -} - TableClient::TableClient( const std::string& serviceUrl, std::shared_ptr credential, @@ -397,28 +306,6 @@ TableClient::TableClient( { } -TableClient TableClient::CreateFromConnectionString( - const std::string& connectionString, - const std::string& tableName, - const TableClientOptions& options) -{ - auto parsedConnectionString = ParseConnectionString(connectionString); - auto tablesUrl = std::move(parsedConnectionString.TableServiceUrl); - - if (parsedConnectionString.KeyCredential) - { - return TableClient( - tableName, - std::move(parsedConnectionString.KeyCredential), - tablesUrl.GetAbsoluteUrl(), - options); - } - else - { - return TableClient(tablesUrl.GetAbsoluteUrl(), tableName, options); - } -} - Azure::Response TableServiceClient::CreateTable( std::string const& tableName, Core::Context const& context) @@ -531,55 +418,6 @@ Models::QueryTablesPagedResponse TableServiceClient::QueryTables( return response; } -Azure::Response TableClient::SetAccessPolicy( - Models::TableAccessPolicy const& tableAccessPolicy, - Core::Context const& context) - -{ - auto url = m_url; - url.AppendPath(m_tableName); - url.AppendQueryParameter(CompHeader, "acl"); - std::string xmlBody = Serializers::SetAccessPolicy(tableAccessPolicy); - Core::IO::MemoryBodyStream requestBody( - reinterpret_cast(xmlBody.data()), xmlBody.length()); - - auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url, &requestBody); - request.SetHeader(ContentTypeHeader, "application/xml; charset=UTF-8"); - request.SetHeader(ContentLengthHeader, std::to_string(requestBody.Length())); - request.GetUrl().AppendQueryParameter(CompHeader, "acl"); - request.SetHeader("x-ms-version", "2019-12-12"); - auto pRawResponse = m_pipeline->Send(request, context); - auto httpStatusCode = pRawResponse->GetStatusCode(); - if (httpStatusCode != Core::Http::HttpStatusCode::NoContent) - { - throw Core::RequestFailedException(pRawResponse); - } - Models::SetTableAccessPolicyResult response; - return Response(std::move(response), std::move(pRawResponse)); -} - -Azure::Response TableClient::GetAccessPolicy( - Core::Context const& context) -{ - auto url = m_url; - url.SetPath(""); - url.AppendPath(m_tableName); - url.AppendQueryParameter(CompHeader, "acl"); - Core::Http::Request request(Core::Http::HttpMethod::Get, url); - - auto pRawResponse = m_pipeline->Send(request, context); - auto const httpStatusCode = pRawResponse->GetStatusCode(); - if (httpStatusCode != Core::Http::HttpStatusCode::Ok) - { - throw Core::RequestFailedException(pRawResponse); - } - const auto& responseBody = pRawResponse->GetBody(); - - Models::TableAccessPolicy response = Serializers::TableAccessPolicyFromXml(responseBody); - - return Response(std::move(response), std::move(pRawResponse)); -} - Azure::Response TableServiceClient::DeleteTable( std::string const& tableName, Core::Context const& context) @@ -920,10 +758,10 @@ Azure::Response TableClient::SubmitTransaction( { auto url = m_url; url.AppendPath("$batch"); - std::string batchId = "batch_" + Azure::Core::Uuid::CreateUuid().ToString(); - std::string changesetId = "changeset_" + Azure::Core::Uuid::CreateUuid().ToString(); + std::string const batchId = "batch_" + Azure::Core::Uuid::CreateUuid().ToString(); + std::string const changesetId = "changeset_" + Azure::Core::Uuid::CreateUuid().ToString(); - std::string body = PreparePayload(batchId, changesetId, steps); + std::string const body = PreparePayload(batchId, changesetId, steps); Core::IO::MemoryBodyStream requestBody( reinterpret_cast(body.data()), body.length()); @@ -1022,8 +860,9 @@ std::string TableClient::PrepAddEntity(std::string const& changesetId, Models::T std::string returnValue = "--" + changesetId + "\n"; returnValue += "Content-Type: application/http\n"; returnValue += "Content-Transfer-Encoding: binary\n\n"; - - returnValue += "POST " + m_url.GetAbsoluteUrl() + "/" + m_tableName + " HTTP/1.1\n"; + auto url = m_url; + url.AppendPath(m_tableName); + returnValue += "POST " + url.GetAbsoluteUrl() + " HTTP/1.1\n"; returnValue += "Content-Type: application/json\n"; returnValue += "Accept: application/json;odata=minimalmetadata\n"; returnValue += "Prefer: return-no-content\n"; @@ -1038,10 +877,11 @@ std::string TableClient::PrepDeleteEntity( std::string returnValue = "--" + changesetId + "\n"; returnValue += "Content-Type: application/http\n"; returnValue += "Content-Transfer-Encoding: binary\n\n"; - - returnValue += "DELETE " + m_url.GetAbsoluteUrl() + "/" + m_tableName + PartitionKeyFragment - + entity.GetPartitionKey().Value + RowKeyFragment + entity.GetRowKey().Value + ClosingFragment - + " HTTP/1.1\n"; + auto url = m_url; + url.AppendPath( + m_tableName + PartitionKeyFragment + entity.GetPartitionKey().Value + RowKeyFragment + + entity.GetRowKey().Value + ClosingFragment); + returnValue += "DELETE " + url.GetAbsoluteUrl() + " HTTP/1.1\n"; returnValue += "Accept: application/json;odata=minimalmetadata\n"; // returnValue += "Prefer: return-no-content\n"; returnValue += "DataServiceVersion: 3.0;\n"; @@ -1062,10 +902,11 @@ std::string TableClient::PrepMergeEntity(std::string const& changesetId, Models: std::string returnValue = "--" + changesetId + "\n"; returnValue += "Content-Type: application/http\n"; returnValue += "Content-Transfer-Encoding: binary\n\n"; - - returnValue += "MERGE " + m_url.GetAbsoluteUrl() + "/" + m_tableName + PartitionKeyFragment - + entity.GetPartitionKey().Value + RowKeyFragment + entity.GetRowKey().Value + ClosingFragment - + " HTTP/1.1\n"; + auto url = m_url; + url.AppendPath( + m_tableName + PartitionKeyFragment + entity.GetPartitionKey().Value + RowKeyFragment + + entity.GetRowKey().Value + ClosingFragment); + returnValue += "MERGE " + url.GetAbsoluteUrl() + " HTTP/1.1\n"; returnValue += "Content-Type: application/json\n"; returnValue += "Accept: application/json;odata=minimalmetadata\n"; returnValue += "DataServiceVersion: 3.0;\n\n"; @@ -1081,10 +922,11 @@ std::string TableClient::PrepUpdateEntity( std::string returnValue = "--" + changesetId + "\n"; returnValue += "Content-Type: application/http\n"; returnValue += "Content-Transfer-Encoding: binary\n\n"; - - returnValue += "PUT " + m_url.GetAbsoluteUrl() + "/" + m_tableName + PartitionKeyFragment - + entity.GetPartitionKey().Value + RowKeyFragment + entity.GetRowKey().Value + ClosingFragment - + " HTTP/1.1\n"; + auto url = m_url; + url.AppendPath( + m_tableName + PartitionKeyFragment + entity.GetPartitionKey().Value + RowKeyFragment + + entity.GetRowKey().Value + ClosingFragment); + returnValue += "PUT " + url.GetAbsoluteUrl() + " HTTP/1.1\n"; returnValue += "Content-Type: application/json\n"; returnValue += "Accept: application/json;odata=minimalmetadata\n"; returnValue += "Prefer: return-no-content\n"; @@ -1110,10 +952,11 @@ std::string TableClient::PrepInsertEntity( std::string returnValue = "--" + changesetId + "\n"; returnValue += "Content-Type: application/http\n"; returnValue += "Content-Transfer-Encoding: binary\n\n"; - - returnValue += "PATCH " + m_url.GetAbsoluteUrl() + "/" + m_tableName + PartitionKeyFragment - + entity.GetPartitionKey().Value + RowKeyFragment + entity.GetRowKey().Value + ClosingFragment - + " HTTP/1.1\n"; + auto url = m_url; + url.AppendPath( + m_tableName + PartitionKeyFragment + entity.GetPartitionKey().Value + RowKeyFragment + + entity.GetRowKey().Value + ClosingFragment); + returnValue += "PATCH " + url.GetAbsoluteUrl() + " HTTP/1.1\n"; returnValue += "Content-Type: application/json\n"; returnValue += "Content-Length: " + std::to_string(payload.length()); returnValue += "Accept: application/json;odata=minimalmetadata\n"; diff --git a/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp b/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp index fa877e8e4..e4b771ea1 100644 --- a/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp +++ b/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp @@ -51,14 +51,6 @@ namespace Azure { namespace Data { namespace Test { std::replace(m_tableName.begin(), m_tableName.end(), '-', '0'); switch (param) { - case AuthType::ConnectionString: - m_tableServiceClient = std::make_shared( - Tables::TableServiceClient::CreateFromConnectionString( - GetConnectionString(), clientOptions)); - m_tableClient = std::make_shared( - Tables::TableClient::CreateFromConnectionString( - GetConnectionString(), m_tableName, tableClientOptions)); - break; case AuthType::Key: m_credential = GetTestCredential(); m_tableServiceClient = std::make_shared( @@ -118,24 +110,6 @@ namespace Azure { namespace Data { namespace Test { StorageTest::TearDown(); } - Azure::Data::Tables::TableClient TablesClientTest::CreateKeyTableClientForTest( - Tables::TableClientOptions& clientOptions) - { - m_tableName = GetTestNameLowerCase() + LowercaseRandomString(10); - auto tableClient - = Tables::TableClient(GetEnv("DATA_TABLES_URL"), m_tableName, m_credential, clientOptions); - return tableClient; - } - - Azure::Data::Tables::TableClient TablesClientTest::CreateTableClientForTest( - Tables::TableClientOptions& clientOptions) - { - m_tableName = GetTestNameLowerCase() + LowercaseRandomString(10); - auto tableClient = Tables::TableClient::CreateFromConnectionString( - GetEnv("STANDARD_STORAGE_CONNECTION_STRING"), m_tableName, clientOptions); - return tableClient; - } - TEST_P(TablesClientTest, ClientConstructor) { EXPECT_FALSE(m_tableClient == nullptr); } TEST_P(TablesClientTest, CreateTable) @@ -159,55 +133,6 @@ namespace Azure { namespace Data { namespace Test { } } - TEST_P(TablesClientTest, GetAccessPolicy) - { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - auto createResponse = m_tableServiceClient->CreateTable(m_tableName); - - auto getResponse = m_tableClient->GetAccessPolicy(); - EXPECT_EQ(getResponse.Value.SignedIdentifiers.size(), 0); - } - - TEST_P(TablesClientTest, SetAccessPolicy) - { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - auto createResponse = m_tableServiceClient->CreateTable(m_tableName); - Azure::Data::Tables::Models::TableAccessPolicy newPolicy{}; - Azure::Data::Tables::Models::SignedIdentifier newIdentifier{}; - newIdentifier.Id = "testid"; - newIdentifier.Permissions = "r"; - newIdentifier.StartsOn = Azure::DateTime::Parse( - Azure::DateTime(std::chrono::system_clock::now()) - .ToString(Azure::DateTime::DateFormat::Rfc1123), - Azure::DateTime::DateFormat::Rfc1123); - newIdentifier.ExpiresOn = Azure::DateTime::Parse( - Azure::DateTime(std::chrono::system_clock::now() + std::chrono::seconds(60)) - .ToString(Azure::DateTime::DateFormat::Rfc1123), - Azure::DateTime::DateFormat::Rfc1123); - newPolicy.SignedIdentifiers.emplace_back(newIdentifier); - - m_tableClient->SetAccessPolicy(newPolicy); - if (GetEnv("AZURE_TEST_MODE") != "PLAYBACK") - { - // setting policy takes up to 30 seconds to take effect - std::this_thread::sleep_for(std::chrono::milliseconds(30001)); - } - - auto getResponse = m_tableClient->GetAccessPolicy(); - - EXPECT_EQ(getResponse.Value.SignedIdentifiers.size(), 1); - EXPECT_EQ(getResponse.Value.SignedIdentifiers[0].Id, newIdentifier.Id); - EXPECT_EQ(getResponse.Value.SignedIdentifiers[0].Permissions, newIdentifier.Permissions); - } - TEST_P(TablesClientTest, ListTables) { auto createResponse = m_tableServiceClient->CreateTable(m_tableName); @@ -574,13 +499,8 @@ namespace Azure { namespace Data { namespace Test { } } - TEST_P(TablesClientTest, TransactionCreateFail) + TEST_P(TablesClientTest, TransactionCreateFail_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -604,14 +524,8 @@ namespace Azure { namespace Data { namespace Test { EXPECT_TRUE(response.Value.Error.HasValue()); } - TEST_P(TablesClientTest, TransactionCreateOK) + TEST_P(TablesClientTest, TransactionCreateOK_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -635,14 +549,8 @@ namespace Azure { namespace Data { namespace Test { EXPECT_FALSE(response.Value.Error.HasValue()); } - TEST_P(TablesClientTest, TransactionDelete) + TEST_P(TablesClientTest, TransactionDelete_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -661,26 +569,18 @@ namespace Azure { namespace Data { namespace Test { Azure::Data::Tables::Models::TransactionActionType::Add, entity}); steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ Azure::Data::Tables::Models::TransactionActionType::Add, entity2}); - auto response = m_tableClient->SubmitTransaction(steps); steps.clear(); // delete entity steps.emplace_back(Azure::Data::Tables::Models::TransactionStep{ Azure::Data::Tables::Models::TransactionActionType::Delete, entity2}); - response = m_tableClient->SubmitTransaction(steps); EXPECT_FALSE(response.Value.Error.HasValue()); } - TEST_P(TablesClientTest, TransactionMerge) + TEST_P(TablesClientTest, TransactionMerge_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -709,14 +609,8 @@ namespace Azure { namespace Data { namespace Test { EXPECT_FALSE(response.Value.Error.HasValue()); } - TEST_P(TablesClientTest, TransactionUpdate) + TEST_P(TablesClientTest, TransactionUpdate_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -743,14 +637,8 @@ namespace Azure { namespace Data { namespace Test { EXPECT_FALSE(response.Value.Error.HasValue()); } - TEST_P(TablesClientTest, TransactionInsertReplace) + TEST_P(TablesClientTest, TransactionInsertReplace_LIVEONLY_) { - if (GetParam() != AuthType::ConnectionString) - { - SkipTest(); - return; - } - Azure::Data::Tables::Models::TableEntity entity; Azure::Data::Tables::Models::TableEntity entity2; entity.SetPartitionKey("P1"); @@ -783,9 +671,6 @@ namespace Azure { namespace Data { namespace Test { std::string stringValue = ""; switch (info.param) { - case AuthType::ConnectionString: - stringValue = "connectionstring_LIVEONLY_"; - break; case AuthType::Key: stringValue = "key"; break; @@ -802,6 +687,6 @@ namespace Azure { namespace Data { namespace Test { INSTANTIATE_TEST_SUITE_P( Tables, TablesClientTest, - ::testing::Values(AuthType::Key, AuthType::ConnectionString, AuthType::SAS), + ::testing::Values(AuthType::Key, AuthType::SAS), GetSuffix); }}} // namespace Azure::Data::Test diff --git a/sdk/tables/azure-data-tables/test/ut/table_client_test.hpp b/sdk/tables/azure-data-tables/test/ut/table_client_test.hpp index e3d9838d7..c996d5a7a 100644 --- a/sdk/tables/azure-data-tables/test/ut/table_client_test.hpp +++ b/sdk/tables/azure-data-tables/test/ut/table_client_test.hpp @@ -12,7 +12,6 @@ namespace Azure { namespace Data { namespace Test { { Key = 0x0, SAS = 0x1, - ConnectionString = 0x2, }; class TablesClientTest : public Azure::Storage::Test::StorageTest, @@ -20,37 +19,39 @@ namespace Azure { namespace Data { namespace Test { protected: void SetUp() override; void TearDown() override; - Azure::Data::Tables::TableClient CreateTableClientForTest( - Tables::TableClientOptions& clientOptions); - - Azure::Data::Tables::TableClient CreateKeyTableClientForTest( - Tables::TableClientOptions& clientOptions); - std::string GetConnectionString() - { - const static std::string ConnectionString = ""; - - if (!ConnectionString.empty()) - { - return ConnectionString; - } - const static std::string envConnectionString = GetEnv("STANDARD_STORAGE_CONNECTION_STRING"); - if (!envConnectionString.empty()) - { - return envConnectionString; - } - throw std::runtime_error("Cannot find connection string."); - } std::string GetAccountName() { - return Azure::Data::Tables::Credentials::_detail::ParseConnectionString(GetConnectionString()) - .AccountName; + static std::string accountName = ""; + + if (!accountName.empty()) + { + return accountName; + } + const static std::string envAccountName = GetEnv("ACCOUNT_NAME"); + if (!envAccountName.empty()) + { + accountName = envAccountName; + return envAccountName; + } + throw std::runtime_error("Cannot find Account Name."); } std::string GetAccountKey() { - return Azure::Data::Tables::Credentials::_detail::ParseConnectionString(GetConnectionString()) - .AccountKey; + static std::string accountKey = ""; + + if (!accountKey.empty()) + { + return accountKey; + } + const static std::string envAccountKey = GetEnv("ACCOUNT_KEY"); + if (!envAccountKey.empty()) + { + accountKey = envAccountKey; + return envAccountKey; + } + throw std::runtime_error("Cannot find Account Key."); } protected: diff --git a/sdk/tables/ci.yml b/sdk/tables/ci.yml index af527e8aa..1316a2891 100644 --- a/sdk/tables/ci.yml +++ b/sdk/tables/ci.yml @@ -36,27 +36,8 @@ extends: Path: azure-data-tables VcpkgPortName: azure-data-tables-cpp TestEnv: - - Name: STANDARD_STORAGE_CONNECTION_STRING - Value: "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333;EndpointSuffix=core.windows.net" - - Name: PREMIUM_FILE_CONNECTION_STRING - Value: "DefaultEndpointsProtocol=https;AccountName=notReal;AccountKey=3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333;EndpointSuffix=core.windows.net" - # Tables related env vars - - Name: STORAGE_TENANT_ID - Value: "72f988bf-86f1-41af-91ab-2d7cd011db47" - - Name: STORAGE_CLIENT_ID - Value: "non-real-client" - - Name: STORAGE_CLIENT_SECRET - Value: "some-secret" - - Name: STORAGE_SUBSCRIPTION_ID - Value: "72f988bf-86f1-41af-91ab-2d7cd011db47" - - Name: STORAGE_RESOURCE_GROUP - Value: "rg-fake" - - Name: TABLES_STORAGE_ACCOUNT_NAME - Value: "account-name" - - Name: LOGGING__LOGLEVEL__DEFAULT - Value: "debug" - - Name: DATA_TABLES_URL - Value: "https://account-name.table.core.windows.net" + - Name: ACCOUNT_NAME + Value: 'account-name' CMakeTestOptions: - Name: Default Value: ''