From fe9002e9054b04a2375da242e49badb1f6880252 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 27 Apr 2021 02:44:03 +0000 Subject: [PATCH] Moving Pageble to Core and updating KeyVault to use it (#2144) * updated getDeletedKeys * pagable for list keys --- sdk/core/azure-core/CHANGELOG.md | 4 + sdk/core/azure-core/CMakeLists.txt | 1 + .../inc/azure/core/paged_response.hpp | 97 +++++++++++++++ .../common/internal/keyvault_pipeline.hpp | 2 +- .../keyvault/common/internal/single_page.hpp | 7 +- .../azure-security-keyvault-keys/CHANGELOG.md | 3 + .../inc/azure/keyvault/keys/key_client.hpp | 23 ++-- .../keys/list_keys_single_page_result.hpp | 117 ++++++++++++++++-- .../src/key_client.cpp | 32 +++-- .../src/list_keys_single_page_result.cpp | 42 ++++++- .../sample3-get-keys/sample3_get_keys.cpp | 46 ++----- .../test/ut/key_client_base_test.hpp | 23 +--- .../test/ut/key_client_get_test_live.cpp | 35 ++---- 13 files changed, 317 insertions(+), 115 deletions(-) create mode 100644 sdk/core/azure-core/inc/azure/core/paged_response.hpp diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index ef31a52ad..391a5ba1c 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -2,6 +2,10 @@ ## 1.0.0-beta.9 (Unreleased) +### New Features + +- Added `Azure::PagedResponse`. + ### Bug Fixes - Do not re-use a libcurl connection to same host but different port. diff --git a/sdk/core/azure-core/CMakeLists.txt b/sdk/core/azure-core/CMakeLists.txt index 653405343..397a4746b 100644 --- a/sdk/core/azure-core/CMakeLists.txt +++ b/sdk/core/azure-core/CMakeLists.txt @@ -75,6 +75,7 @@ set( inc/azure/core/modified_conditions.hpp inc/azure/core/nullable.hpp inc/azure/core/operation.hpp + inc/azure/core/paged_response.hpp inc/azure/core/operation_status.hpp inc/azure/core/platform.hpp inc/azure/core/response.hpp diff --git a/sdk/core/azure-core/inc/azure/core/paged_response.hpp b/sdk/core/azure-core/inc/azure/core/paged_response.hpp new file mode 100644 index 000000000..79ac9eb97 --- /dev/null +++ b/sdk/core/azure-core/inc/azure/core/paged_response.hpp @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +/** + * @file + * @brief Provides support for responses of paginated collections from the service. + */ + +#pragma once + +#include +#include + +#include "azure/core/context.hpp" +#include "azure/core/http/raw_response.hpp" +#include "azure/core/nullable.hpp" + +namespace Azure { namespace Core { + + /** + * @brief Defines the base type and behavior for a paged response. + * + * @remark The template is used for static-inheritance. + * + * @remark T classes must implement the way to get and move to the next page. + * + * @tparam T A class type for static-inheritance. + */ + template class PagedResponse { + private: + // The field used to check when the end of the response is reached. We default it true as the + // starting point because all responses from a service will always come with a payload that + // represents at least one page. The page might or might not contain elements in the page. + // `m_hasPage` is then turned to `false` once `MoveToNextPage` is called on the last page. + bool m_hasPage = true; + + protected: + PagedResponse() = default; + PagedResponse(PagedResponse&&) = default; + PagedResponse& operator=(PagedResponse&&) = default; + + public: + /** + * @brief Defines the token used to fetch the current page. + * + */ + std::string CurrentPageToken; + + /** + * @brief Defines the token for getting the next page. + * + * @remark If there are no more pages, this field becomes an empty string. + * + * @remark Assumes all services will include NextPageToken in the payload, it is set to either + * null or empty for the last page or to a value used for getting the next page. + * + */ + Azure::Nullable NextPageToken; + + /** + * @brief The HTTP response returned by the service. + * + */ + std::unique_ptr RawResponse; + + /** + * @brief Check if a page exists. It returns false after the last page. + * + */ + bool HasPage() const { return m_hasPage; } + + /** + * @brief Move to the next page of the response. + * + * @remark Calling this method on the last page will set #HasPage() to false. + * + * @param context An #Azure::Core::Context controlling the request lifetime. + */ + void MoveToNextPage(const Azure::Core::Context& context = Azure::Core::Context()) + { + static_assert( + std::is_base_of::value, + "The template argument \"T\" should derive from PagedResponse."); + + if (!NextPageToken.HasValue() || NextPageToken.Value().empty()) + { + m_hasPage = false; + return; + } + + // Developer must make sure current page is kept unchanged if OnNextPage() + // throws exception. + static_cast(this)->OnNextPage(context); + } + }; + +}} // namespace Azure::Core diff --git a/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/keyvault_pipeline.hpp b/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/keyvault_pipeline.hpp index 5a1b1f8a0..3ca2f4633 100644 --- a/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/keyvault_pipeline.hpp +++ b/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/keyvault_pipeline.hpp @@ -113,7 +113,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace _internal // Saving the value in a local is required before passing it in to Response to avoid // compiler optimizations re-ordering the `factoryFn` function call and the RawResponse move. T value = factoryFn(*response); - return Azure::Response(value, std::move(response)); + return Azure::Response(std::move(value), std::move(response)); } /** diff --git a/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/single_page.hpp b/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/single_page.hpp index 7ea87711a..0c5e551af 100644 --- a/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/single_page.hpp +++ b/sdk/keyvault/azure-security-keyvault-common/inc/azure/keyvault/common/internal/single_page.hpp @@ -13,14 +13,9 @@ #include namespace Azure { namespace Security { namespace KeyVault { namespace _internal { - struct SinglePage - { - Azure::Nullable ContinuationToken; - }; - struct GetSinglePageOptions { - Azure::Nullable ContinuationToken; + Azure::Nullable NextPageToken; Azure::Nullable MaxPageResults; }; }}}} // namespace Azure::Security::KeyVault::_internal diff --git a/sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md b/sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md index e18ba84e9..b8a3d9b44 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md +++ b/sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md @@ -12,6 +12,9 @@ - Replaced static functions from `KeyOperation` and `KeyCurveName` with static const members. - Replaced the enum `JsonWebKeyType` for a class with static const members as an extensible enum called `KeyVaultKeyType`. - Renamed `MaxResults` to `MaxPageResults` for `GetSinglePageOptions`. +- Changed the returned type for list keys, key versions, and deleted keys from `Response` to `PagedResponse` affecting: + - `GetPropertiesOfKeysSinglePage()` and `GetPropertiesOfKeyVersionsSinglePage()` now returns `KeyPropertiesSinglePage`. + - `GetDeletedKeysSinglePage()` now returns `DeletedKeySinglePage`. ### Bug Fixes diff --git a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp index 80fa1f870..822e0d7ed 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp @@ -73,6 +73,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { std::shared_ptr credential, KeyClientOptions options = KeyClientOptions()); + /** + * @brief Construct a new Key Client object from another key client. + * + * @param keyClient An existing key vault key client. + */ + explicit KeyClient(KeyClient const& keyClient) : m_pipeline(keyClient.m_pipeline) {} + /** * @brief Gets the public part of a stored key. * @@ -168,15 +175,14 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * * @remark Use \p options to control which page to get. If * #GetPropertiesOfKeysSinglePageOptions.NextLink is not set, the operation will get the first - * page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the next + * page and it will set the `NextPageToken` from the #KeyPropertiesSinglePage as the next * page of the response if there is a next page. * * @param options The #GetPropertiesOfKeysSinglePageOptions object to for setting the operation * up. * @param context A #Azure::Core::Context controlling the request lifetime. - * @return Azure::Response */ - Azure::Response GetPropertiesOfKeysSinglePage( + KeyPropertiesSinglePage GetPropertiesOfKeysSinglePage( GetPropertiesOfKeysSinglePageOptions const& options = GetPropertiesOfKeysSinglePageOptions(), Azure::Core::Context const& context = Azure::Core::Context()) const; @@ -191,16 +197,15 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * * @remark Use \p options to control which page to get. If * #GetPropertiesOfKeyVersionsSinglePageOptions.NextLink is not set, the operation will get the - * first page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the + * first page and it will set the `NextPageToken` from the #KeyPropertiesSinglePage as the * next page of the response if there is a next page. * * @param name The name of the key. * @param options The #GetPropertiesOfKeyVersionsSinglePageOptions object to for setting the * operation up. * @param context A #Azure::Core::Context controlling the request lifetime. - * @return Azure::Response */ - Azure::Response GetPropertiesOfKeyVersionsSinglePage( + KeyPropertiesSinglePage GetPropertiesOfKeyVersionsSinglePage( std::string const& name, GetPropertiesOfKeyVersionsSinglePageOptions const& options = GetPropertiesOfKeyVersionsSinglePageOptions(), @@ -262,15 +267,15 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * requires the keys/list permission. * * @remark Use \p options to control which page to get. If - * #GetPropertiesOfKeyVersionsSinglePageOptions.NextLink is not set, the operation will get the - * first page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the + * #GetPropertiesOfKeyVersionsSinglePageOptions.NextPageToken is not set, the operation will get + * the first page and it will set the `NextPageToken` from the #KeyPropertiesSinglePage as the * next page of the response if there is a next page. * * @param options The #GetDeletedKeysSinglePageOptions object to for setting the operation up. * @param context A #Azure::Core::Context controlling the request lifetime. * @return Azure::Response */ - Azure::Response GetDeletedKeysSinglePage( + DeletedKeySinglePage GetDeletedKeysSinglePage( GetDeletedKeysSinglePageOptions const& options = GetDeletedKeysSinglePageOptions(), Azure::Core::Context const& context = Azure::Core::Context()) const; diff --git a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/list_keys_single_page_result.hpp b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/list_keys_single_page_result.hpp index c00685b3f..5502858ac 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/list_keys_single_page_result.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/list_keys_single_page_result.hpp @@ -9,38 +9,139 @@ #pragma once +#include +#include + +#include + #include "azure/keyvault/keys/deleted_key.hpp" #include "azure/keyvault/keys/json_web_key.hpp" #include "azure/keyvault/keys/key_vault_key.hpp" -#include - -#include - +#include #include namespace Azure { namespace Security { namespace KeyVault { namespace Keys { + class KeyClient; - struct KeyPropertiesSinglePage : public Azure::Security::KeyVault::_internal::SinglePage - { + /** + * @brief Define a single page to list the keys from the Key Vault. + * + */ + class KeyPropertiesSinglePage : public Azure::Core::PagedResponse { + private: + friend class KeyClient; + friend class Azure::Core::PagedResponse; + + std::string m_keyName; + std::shared_ptr m_keyClient; + void OnNextPage(const Azure::Core::Context&); + + /** + * @brief Construct a new Key Properties Single Page object. + * + * @remark The constructor is private and only a key client or PagedResponse can init this. + * + * @param keyProperties A previously created #KeyPropertiesSinglePage that is used to init this + * instance. + * @param rawResponse The Http raw response from where the #KeyPropertiesSinglePage was parsed. + * @param keyClient A key client required for getting the next pages. + * @param keyName When \p keyName is set, the response is listing key versions. Otherwise, the + * response is for listing keys from the Key Vault. + */ + KeyPropertiesSinglePage( + KeyPropertiesSinglePage&& keyProperties, + std::unique_ptr rawResponse, + std::shared_ptr keyClient, + std::string const& keyName = std::string()) + : m_keyName(keyName), m_keyClient(keyClient), Items(std::move(keyProperties.Items)) + { + RawResponse = std::move(rawResponse); + } + + public: + /** + * @brief Construct a new key properties object. + * + */ + KeyPropertiesSinglePage() = default; + + /** + * @brief Each #KeyProperties represent a Key in the Key Vault. + * + */ std::vector Items; }; - struct DeletedKeySinglePage : public Azure::Security::KeyVault::_internal::SinglePage - { + /** + * @brief Define a single page containing the deleted keys from the Key Vault. + * + */ + class DeletedKeySinglePage : public Azure::Core::PagedResponse { + private: + friend class KeyClient; + friend class Azure::Core::PagedResponse; + + std::shared_ptr m_keyClient; + void OnNextPage(const Azure::Core::Context& context); + + /** + * @brief Construct a new Key Properties Single Page object. + * + * @remark The constructor is private and only a key client or PagedResponse can init this. + * + * @param deletedKeyProperties A previously created #DeletedKeySinglePage that is used to init + * this new instance. + * @param rawResponse The Http raw response from where the #DeletedKeySinglePage was parsed. + * @param keyClient A key client required for getting the next pages. + * @param keyName When \p keyName is set, the response is listing key versions. Otherwise, the + * response is for listing keys from the Key Vault. + */ + DeletedKeySinglePage( + DeletedKeySinglePage&& deletedKeyProperties, + std::unique_ptr rawResponse, + std::shared_ptr keyClient) + : m_keyClient(keyClient), Items(std::move(deletedKeyProperties.Items)) + { + RawResponse = std::move(rawResponse); + } + + public: + /** + * @brief Construct a new Deleted Key Single Page object + * + */ + DeletedKeySinglePage() = default; + + /** + * @brief Each #DeletedKey represent a deleted key in the Key Vault. + * + */ std::vector Items; }; + /** + * @brief The options for calling an operation #GetPropertiesOfKeysSinglePage. + * + */ struct GetPropertiesOfKeysSinglePageOptions : public Azure::Security::KeyVault::_internal::GetSinglePageOptions { }; + /** + * @brief The options for calling an operation #GetPropertiesOfKeyVersionsSinglePage. + * + */ struct GetPropertiesOfKeyVersionsSinglePageOptions : public Azure::Security::KeyVault::_internal::GetSinglePageOptions { }; + /** + * @brief The options for calling an operation #GetDeletedKeysSinglePage. + * + */ struct GetDeletedKeysSinglePageOptions : public Azure::Security::KeyVault::_internal::GetSinglePageOptions { diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp index 25ee50d34..4ed46b811 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp @@ -35,11 +35,11 @@ static inline RequestWithContinuationToken BuildRequestFromContinuationToken( { RequestWithContinuationToken request; request.Path = defaultPath; - if (options.ContinuationToken) + if (options.NextPageToken) { // Using a continuation token requires to send the request to the continuation token url instead // of the default url which is used only for the first page. - Azure::Core::Url nextPageUrl(options.ContinuationToken.Value()); + Azure::Core::Url nextPageUrl(options.NextPageToken.Value()); request.Query = std::make_unique>(nextPageUrl.GetQueryParameters()); request.Path.clear(); @@ -155,12 +155,12 @@ Azure::Response KeyClient::CreateOctKey( {_detail::KeysPath, keyName, "create"}); } -Azure::Response KeyClient::GetPropertiesOfKeysSinglePage( +KeyPropertiesSinglePage KeyClient::GetPropertiesOfKeysSinglePage( GetPropertiesOfKeysSinglePageOptions const& options, Azure::Core::Context const& context) const { auto const request = BuildRequestFromContinuationToken(options, {_detail::KeysPath}); - return m_pipeline->SendRequest( + auto response = m_pipeline->SendRequest( context, Azure::Core::Http::HttpMethod::Get, [](Azure::Core::Http::RawResponse const& rawResponse) { @@ -169,16 +169,21 @@ Azure::Response KeyClient::GetPropertiesOfKeysSinglePag }, request.Path, request.Query); + + return KeyPropertiesSinglePage( + std::move(response.Value), + std::move(response.RawResponse), + std::make_unique(*this)); } -Azure::Response KeyClient::GetPropertiesOfKeyVersionsSinglePage( +KeyPropertiesSinglePage KeyClient::GetPropertiesOfKeyVersionsSinglePage( std::string const& name, GetPropertiesOfKeyVersionsSinglePageOptions const& options, Azure::Core::Context const& context) const { auto const request = BuildRequestFromContinuationToken(options, {_detail::KeysPath, name, "versions"}); - return m_pipeline->SendRequest( + auto response = m_pipeline->SendRequest( context, Azure::Core::Http::HttpMethod::Get, [](Azure::Core::Http::RawResponse const& rawResponse) { @@ -187,6 +192,12 @@ Azure::Response KeyClient::GetPropertiesOfKeyVersionsSi }, request.Path, request.Query); + + return KeyPropertiesSinglePage( + std::move(response.Value), + std::move(response.RawResponse), + std::make_unique(*this), + name); } Azure::Security::KeyVault::Keys::DeleteKeyOperation KeyClient::StartDeleteKey( @@ -254,12 +265,12 @@ Azure::Response KeyClient::GetDeletedKey( {_detail::DeletedKeysPath, name}); } -Azure::Response KeyClient::GetDeletedKeysSinglePage( +DeletedKeySinglePage KeyClient::GetDeletedKeysSinglePage( GetDeletedKeysSinglePageOptions const& options, Azure::Core::Context const& context) const { auto const request = BuildRequestFromContinuationToken(options, {_detail::DeletedKeysPath}); - return m_pipeline->SendRequest( + auto response = m_pipeline->SendRequest( context, Azure::Core::Http::HttpMethod::Get, [](Azure::Core::Http::RawResponse const& rawResponse) { @@ -268,6 +279,11 @@ Azure::Response KeyClient::GetDeletedKeysSinglePage( }, request.Path, request.Query); + + return DeletedKeySinglePage( + std::move(response.Value), + std::move(response.RawResponse), + std::make_unique(*this)); } Azure::Response KeyClient::PurgeDeletedKey( diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/list_keys_single_page_result.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/list_keys_single_page_result.cpp index 1d7b9c2a6..b689b42da 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/list_keys_single_page_result.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/src/list_keys_single_page_result.cpp @@ -4,6 +4,7 @@ #include "azure/keyvault/keys/list_keys_single_page_result.hpp" #include "azure/keyvault/keys/details/key_constants.hpp" #include "azure/keyvault/keys/details/key_serializers.hpp" +#include "azure/keyvault/keys/key_client.hpp" #include @@ -24,7 +25,7 @@ _detail::KeyPropertiesSinglePageSerializer::KeyPropertiesSinglePageDeserialize( auto const& body = rawResponse.GetBody(); auto jsonParser = json::parse(body); - JsonOptional::SetIfExists(result.ContinuationToken, jsonParser, "nextLink"); + JsonOptional::SetIfExists(result.NextPageToken, jsonParser, "nextLink"); // Key properties auto keyPropertiesJson = jsonParser["value"]; @@ -90,7 +91,8 @@ DeletedKeySinglePage _detail::KeyPropertiesSinglePageSerializer::DeletedKeySingl auto jsonParser = Azure::Core::Json::_internal::json::parse(body); DeletedKeySinglePage deletedKeySinglePage; - JsonOptional::SetIfExists(deletedKeySinglePage.ContinuationToken, jsonParser, "nextLink"); + + JsonOptional::SetIfExists(deletedKeySinglePage.NextPageToken, jsonParser, "nextLink"); auto deletedKeys = jsonParser["value"]; for (auto const& key : deletedKeys) @@ -125,3 +127,39 @@ DeletedKeySinglePage _detail::KeyPropertiesSinglePageSerializer::DeletedKeySingl return deletedKeySinglePage; } + +void DeletedKeySinglePage::OnNextPage(const Azure::Core::Context& context) +{ + // Before calling `OnNextPage` pagedResponse validates there is a next page, so we are sure + // NextPageToken is valid. + GetDeletedKeysSinglePageOptions options; + options.NextPageToken = NextPageToken; + *this = m_keyClient->GetDeletedKeysSinglePage(options, context); + CurrentPageToken = options.NextPageToken.Value(); +} + +void KeyPropertiesSinglePage::OnNextPage(const Azure::Core::Context& context) +{ + // Notes + // - Before calling `OnNextPage` pagedResponse validates there is a next page, so we are sure + // NextPageToken is valid. + // - KeyPropertiesSinglePage is used to list keys from a Key Vault and also to list the key + // versions from a specific key. When KeyPropertiesSinglePage is listing keys, the `m_keyName` + // fields will be empty, but for listing the key versions, the KeyPropertiesSinglePage needs to + // keep the name of the key in `m_keyName` because it is required to get more pages. + // + if (m_keyName.empty()) + { + GetPropertiesOfKeysSinglePageOptions options; + options.NextPageToken = NextPageToken; + *this = m_keyClient->GetPropertiesOfKeysSinglePage(options, context); + CurrentPageToken = options.NextPageToken.Value(); + } + else + { + GetPropertiesOfKeyVersionsSinglePageOptions options; + options.NextPageToken = NextPageToken; + *this = m_keyClient->GetPropertiesOfKeyVersionsSinglePage(m_keyName, options, context); + CurrentPageToken = options.NextPageToken.Value(); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/samples/sample3-get-keys/sample3_get_keys.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/samples/sample3-get-keys/sample3_get_keys.cpp index c6b32631f..6cfae8770 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/samples/sample3-get-keys/sample3_get_keys.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/samples/sample3-get-keys/sample3_get_keys.cpp @@ -56,7 +56,8 @@ int main() keyClient.CreateEcKey(ecKey); std::cout << "\t-List Keys" << std::endl; - for (auto keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage().Value;;) + for (auto keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage(); keysSinglePage.HasPage(); + keysSinglePage.MoveToNextPage()) { for (auto const& key : keysSinglePage.Items) { @@ -68,17 +69,6 @@ int main() std::cout << "Key is returned with name: " << keyWithType.Name() << " and type: " << keyWithType.GetKeyType().ToString() << std::endl; } - - if (!keysSinglePage.ContinuationToken.HasValue()) - { - // No more pages for the response, break the loop - break; - } - - // Get the next page - GetPropertiesOfKeysSinglePageOptions options; - options.ContinuationToken = keysSinglePage.ContinuationToken.Value(); - keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage(options).Value; } // update key @@ -90,26 +80,14 @@ int main() // List key versions std::cout << "\t-List Key versions" << std::endl; - for (auto keyVersionsSinglePage - = keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName).Value; - ;) + for (auto keyVersionsSinglePage = keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName); + keyVersionsSinglePage.HasPage(); + keyVersionsSinglePage.MoveToNextPage()) { for (auto const& key : keyVersionsSinglePage.Items) { std::cout << "Key's version: " << key.Version << " with name: " << key.Name << std::endl; } - - if (!keyVersionsSinglePage.ContinuationToken.HasValue()) - { - // No more pages for the response, break the loop - break; - } - - // Get the next page - GetPropertiesOfKeyVersionsSinglePageOptions options; - options.ContinuationToken = keyVersionsSinglePage.ContinuationToken.Value(); - keyVersionsSinglePage - = keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName, options).Value; } std::cout << "\t-Delete Keys" << std::endl; @@ -123,7 +101,8 @@ int main() std::cout << "\t-List Deleted Keys" << std::endl; // Start getting the first page. - for (auto keysDeletedPage = keyClient.GetDeletedKeysSinglePage().Value;;) + for (auto keysDeletedPage = keyClient.GetDeletedKeysSinglePage(); keysDeletedPage.HasPage(); + keysDeletedPage.MoveToNextPage()) { for (auto const& key : keysDeletedPage.Items) { @@ -131,17 +110,6 @@ int main() << ", recovery level: " << key.Properties.RecoveryLevel << " and recovery Id: " << key.RecoveryId << std::endl; } - - if (!keysDeletedPage.ContinuationToken.HasValue()) - { - // No more pages for the response, break the loop - break; - } - - // Get the next page - GetDeletedKeysSinglePageOptions options; - options.ContinuationToken = keysDeletedPage.ContinuationToken.Value(); - keysDeletedPage = keyClient.GetDeletedKeysSinglePage(options).Value; } // If the keyvault is soft-delete enabled, then for permanent deletion, deleted keys needs to be diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_base_test.hpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_base_test.hpp index 879084eca..670f290b1 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_base_test.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_base_test.hpp @@ -70,19 +70,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam static inline void CleanUpKeyVault(KeyClient const& keyClient) { std::vector deletedKeys; - GetDeletedKeysSinglePageOptions options; - while (true) + for (auto keyResponse = keyClient.GetDeletedKeysSinglePage(); keyResponse.HasPage(); + keyResponse.MoveToNextPage()) { - auto keyResponse = keyClient.GetDeletedKeysSinglePage(options); - for (auto& key : keyResponse.Value.Items) + for (auto& key : keyResponse.Items) { deletedKeys.emplace_back(key); } - if (!keyResponse.Value.ContinuationToken) - { - break; - } - options.ContinuationToken = keyResponse.Value.ContinuationToken; } if (deletedKeys.size() > 0) { @@ -99,18 +93,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam { std::vector deletedKeys; GetPropertiesOfKeysSinglePageOptions options; - while (true) + for (auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(); keyResponse.HasPage(); + keyResponse.MoveToNextPage()) { - auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(options); - for (auto& key : keyResponse.Value.Items) + for (auto& key : keyResponse.Items) { deletedKeys.emplace_back(keyClient.StartDeleteKey(key.Name)); } - if (!keyResponse.Value.ContinuationToken) - { - break; - } - options.ContinuationToken = keyResponse.Value.ContinuationToken; } if (deletedKeys.size() > 0) { diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_get_test_live.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_get_test_live.cpp index ef6e60068..f28050595 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_get_test_live.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_get_test_live.cpp @@ -53,18 +53,13 @@ TEST_F(KeyVaultClientTest, GetPropertiesOfKeysOnePage) // Get Key properties std::vector keyPropertiesList; GetPropertiesOfKeysSinglePageOptions options; - while (true) + for (auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(options); keyResponse.HasPage(); + keyResponse.MoveToNextPage()) { - auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(options); - for (auto& key : keyResponse.Value.Items) + for (auto& key : keyResponse.Items) { keyPropertiesList.emplace_back(key); } - if (!keyResponse.Value.ContinuationToken) - { - break; - } - options.ContinuationToken = keyResponse.Value.ContinuationToken; } EXPECT_EQ(keyNames.size(), keyPropertiesList.size()); @@ -95,18 +90,14 @@ TEST_F(KeyVaultClientTest, GetKeysVersionsOnePage) // Get Key versions std::vector keyPropertiesList; GetPropertiesOfKeyVersionsSinglePageOptions getKeyOptions; - while (true) + for (auto keyResponse = keyClient.GetPropertiesOfKeyVersionsSinglePage(keyName); + keyResponse.HasPage(); + keyResponse.MoveToNextPage()) { - auto keyResponse = keyClient.GetPropertiesOfKeyVersionsSinglePage(keyName, getKeyOptions); - for (auto& key : keyResponse.Value.Items) + for (auto& key : keyResponse.Items) { keyPropertiesList.emplace_back(key); } - if (!keyResponse.Value.ContinuationToken) - { - break; - } - getKeyOptions.ContinuationToken = keyResponse.Value.ContinuationToken; } EXPECT_EQ(expectedVersions, keyPropertiesList.size()); @@ -150,19 +141,13 @@ TEST_F(KeyVaultClientTest, GetDeletedKeysOnePage) // Get all deleted Keys std::vector deletedKeys; - GetDeletedKeysSinglePageOptions options; - while (true) + for (auto keyResponse = keyClient.GetDeletedKeysSinglePage(); keyResponse.HasPage(); + keyResponse.MoveToNextPage()) { - auto keyResponse = keyClient.GetDeletedKeysSinglePage(options); - for (auto& key : keyResponse.Value.Items) + for (auto& key : keyResponse.Items) { deletedKeys.emplace_back(key); } - if (!keyResponse.Value.ContinuationToken) - { - break; - } - options.ContinuationToken = keyResponse.Value.ContinuationToken; } EXPECT_EQ(keyNames.size(), deletedKeys.size());