From d46cdad67fa5d00830fcf5aa24223740bc9d5310 Mon Sep 17 00:00:00 2001 From: Ahson Khan Date: Fri, 8 Nov 2024 12:28:18 -0800 Subject: [PATCH] Add project skeleton and check-in snapshot of generated SDK for Azure App Configuration. (#6176) * Add project skeleton and check-in snapshot of generated SDK for Azure App Configuration. * Add new line at eof * Add exclusion to the cspell issue. * Explicitly use size_t instead of auto for iterating through a vector * Add another cspell exclusion, since it is case-sensitive * Address PR feedback, update CL, package version. * Update readme to remove template project content. * Exclude appconfig from recordings, since none exist atm. * Temporarily exclude appconfiguration from docs generation. * Add line/branch coverage thresholds and skip publishing docs if they don't exist. --- .github/CODEOWNERS | 5 + .vscode/cspell.json | 2 + CMakeLists.txt | 1 + .../templates/jobs/archetype-sdk-client.yml | 8 + eng/pipelines/templates/jobs/ci.tests.yml | 2 +- sdk/appconfiguration/CMakeLists.txt | 11 + .../azure-data-appconfiguration/CHANGELOG.md | 13 + .../CMakeLists.txt | 101 + .../azure-data-appconfiguration/NOTICE.txt | 32 + .../azure-data-appconfiguration/README.md | 66 + .../cgmanifest.json | 37 + .../inc/ApiViewSettings.json | 18 + .../inc/azure/data/appconfiguration.hpp | 15 + .../appconfiguration/configuration_client.hpp | 156 ++ .../configuration_client_models.hpp | 614 +++++ .../configuration_client_options.hpp | 239 ++ .../appconfiguration/dll_import_export.hpp | 40 + .../inc/azure/data/appconfiguration/rtti.hpp | 36 + .../src/configuration_client.cpp | 2318 +++++++++++++++++ .../src/private/package_version.hpp | 68 + .../test/ut/CMakeLists.txt | 35 + .../test/ut/configuration_test.cpp | 16 + .../test/ut/macro_guard.cpp | 15 + .../azure-data-appconfiguration/vcpkg.json | 22 + .../vcpkg/Config.cmake.in | 11 + .../vcpkg/portfile.cmake | 36 + .../vcpkg/vcpkg.json | 32 + sdk/appconfiguration/ci.yml | 35 + 28 files changed, 3983 insertions(+), 1 deletion(-) create mode 100644 sdk/appconfiguration/CMakeLists.txt create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/CHANGELOG.md create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/CMakeLists.txt create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/NOTICE.txt create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/README.md create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/cgmanifest.json create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/ApiViewSettings.json create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_models.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_options.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/dll_import_export.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/rtti.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/src/configuration_client.cpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/src/private/package_version.hpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/test/ut/CMakeLists.txt create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/test/ut/configuration_test.cpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/test/ut/macro_guard.cpp create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/vcpkg.json create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/vcpkg/Config.cmake.in create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/vcpkg/portfile.cmake create mode 100644 sdk/appconfiguration/azure-data-appconfiguration/vcpkg/vcpkg.json create mode 100644 sdk/appconfiguration/ci.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c6033ffa4..da9313899 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,6 +32,11 @@ # Client SDKs ########### +# AzureSdkOwners: @ahsonkhan +# ServiceLabel: %App Configuration +# PRLabel: %App Configuration +/sdk/appconfiguration/ @ahsonkhan @LarryOsterman @antkmsft @gearama @RickWinter + # ServiceOwners: @gkostal @anilba06 @ahmadmsft # ServiceLabel: %Attestation diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 9d2845cc1..d5218a15f 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -153,6 +153,8 @@ "Kirilov", "koreacentral", "Kouhei", + "kvset", + "Kvset", "lcov", "LIBCMTD", "LINUXNEXTVMIMAGE", diff --git a/CMakeLists.txt b/CMakeLists.txt index 325097191..b88178f18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,7 @@ endif() # sub-projects add_subdirectory(sdk/core) +add_subdirectory(sdk/appconfiguration) add_subdirectory(sdk/attestation) # AMQP doesn't work for UWP yet, and eventhubs depends on AMQP, so we cannot include eventhubs on UWP. if (NOT BUILD_WINDOWS_UWP) diff --git a/eng/pipelines/templates/jobs/archetype-sdk-client.yml b/eng/pipelines/templates/jobs/archetype-sdk-client.yml index c22a9527a..d13e0095b 100644 --- a/eng/pipelines/templates/jobs/archetype-sdk-client.yml +++ b/eng/pipelines/templates/jobs/archetype-sdk-client.yml @@ -244,6 +244,12 @@ jobs: - script: cmake --build . --target ${{ artifact.Path }}-docs workingDirectory: build displayName: Generate docs (${{ artifact.Name }}-docs) + condition: and(succeeded(), ne('${{parameters.ServiceDirectory}}', 'appconfiguration')) + + - pwsh: | + $docsfileExists = Test-Path -Path "build/sdk/${{ parameters.ServiceDirectory }}/${{ artifact.Path }}/docs/html" + Write-Output "##vso[task.setvariable variable=DocsFileExists]$docsfileExists" + displayName: Check if docs exist for ${{ artifact.Name }} - template: /eng/common/pipelines/templates/steps/verify-links.yml parameters: @@ -252,6 +258,7 @@ jobs: CheckLinkGuidance: $false Recursive: $true WorkingDirectory: build/sdk/${{ parameters.ServiceDirectory }}/${{ artifact.Path }}/docs/html + condition: and(succeeded(), eq(variables['DocsFileExists'], True)) - task: PowerShell@2 inputs: @@ -350,5 +357,6 @@ jobs: parameters: ArtifactPath: $(Build.ArtifactStagingDirectory)/docs ArtifactName: docs + CustomCondition: eq(variables['DocsFileExists'], True) - template: /eng/common/pipelines/templates/steps/eng-common-workflow-enforcer.yml diff --git a/eng/pipelines/templates/jobs/ci.tests.yml b/eng/pipelines/templates/jobs/ci.tests.yml index 6c0c6646c..643e11cf3 100644 --- a/eng/pipelines/templates/jobs/ci.tests.yml +++ b/eng/pipelines/templates/jobs/ci.tests.yml @@ -216,7 +216,7 @@ jobs: test-proxy restore -a $(Build.SourcesDirectory)/sdk/${{parameters.ServiceDirectory}} workingDirectory: '$(Build.SourcesDirectory)/sdk/${{parameters.ServiceDirectory}}' displayName: Restore Recordings - condition: and(succeeded(), contains(variables.CmakeArgs, 'BUILD_TESTING=ON'), ne('${{parameters.ServiceDirectory}}', 'core'),ne('${{parameters.ServiceDirectory}}', 'template')) + condition: and(succeeded(), contains(variables.CmakeArgs, 'BUILD_TESTING=ON'), ne('${{parameters.ServiceDirectory}}', 'core'), ne('${{parameters.ServiceDirectory}}', 'template'), ne('${{parameters.ServiceDirectory}}', 'appconfiguration')) name: RestoreRecordings - pwsh: | diff --git a/sdk/appconfiguration/CMakeLists.txt b/sdk/appconfiguration/CMakeLists.txt new file mode 100644 index 000000000..472d792dc --- /dev/null +++ b/sdk/appconfiguration/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +cmake_minimum_required (VERSION 3.13) + +project (azure-data-appconfiguration LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +add_subdirectory(azure-data-appconfiguration) diff --git a/sdk/appconfiguration/azure-data-appconfiguration/CHANGELOG.md b/sdk/appconfiguration/azure-data-appconfiguration/CHANGELOG.md new file mode 100644 index 000000000..40e0ac14f --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/CHANGELOG.md @@ -0,0 +1,13 @@ +# Release History + +## 1.0.0-beta.1 (Unreleased) + +### Features Added + +- Initial release. + +### Breaking Changes + +### Bugs Fixed + +### Other Changes diff --git a/sdk/appconfiguration/azure-data-appconfiguration/CMakeLists.txt b/sdk/appconfiguration/azure-data-appconfiguration/CMakeLists.txt new file mode 100644 index 000000000..26c667190 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/CMakeLists.txt @@ -0,0 +1,101 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +# setting CMAKE_TOOLCHAIN_FILE must happen before creating the project +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake-modules") +include(AzureVcpkg) +az_vcpkg_integrate() + +cmake_minimum_required (VERSION 3.13) +project(azure-data-appconfiguration LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +if(NOT AZ_ALL_LIBRARIES) + find_package(azure-core-cpp CONFIG QUIET) + if(NOT azure-core-cpp_FOUND) + find_package(azure-core-cpp REQUIRED) + endif() +endif() + +include(AzureVersion) +include(AzureCodeCoverage) +include(AzureTransportAdapters) +include(AzureDoxygen) +include(AzureGlobalCompileOptions) +include(AzureConfigRTTI) +include(AzureBuildTargetForCI) +# Add create_map_file function +include(CreateMapFile) + +if(NOT AZ_ALL_LIBRARIES) + find_package(azure-core-cpp CONFIG QUIET) + if(NOT azure-core-cpp_FOUND) + find_package(azure-core-cpp REQUIRED) + endif() +endif() + +set( + AZURE_DATA_APPCONFIGURATION_HEADER + inc/azure/data/appconfiguration.hpp + inc/azure/data/appconfiguration/configuration_client.hpp + inc/azure/data/appconfiguration/configuration_client_models.hpp + inc/azure/data/appconfiguration/configuration_client_options.hpp + inc/azure/data/appconfiguration/dll_import_export.hpp + inc/azure/data/appconfiguration/rtti.hpp +) + +set( + AZURE_DATA_APPCONFIGURATION_SOURCE + src/private/package_version.hpp + src/configuration_client.cpp +) + +add_library(azure-data-appconfiguration ${AZURE_DATA_APPCONFIGURATION_HEADER} ${AZURE_DATA_APPCONFIGURATION_SOURCE}) + +target_compile_definitions(azure-data-appconfiguration PRIVATE _azure_BUILDING_SDK) + +create_per_service_target_build(appconfiguration azure-data-appconfiguration) + +target_include_directories( + azure-data-appconfiguration + PUBLIC + $ + $ +) + +target_link_libraries(azure-data-appconfiguration PUBLIC Azure::azure-core) + +# make sure that users can consume the project as a library. +add_library(Azure::azure-data-appconfiguration ALIAS azure-data-appconfiguration) + +# coverage. Has no effect if BUILD_CODE_COVERAGE is OFF +create_code_coverage(appconfiguration azure-data-appconfiguration azure-data-appconfiguration-test "tests?/*;samples?/*") + +get_az_version("${CMAKE_CURRENT_SOURCE_DIR}/src/private/package_version.hpp") +set_target_properties(azure-data-appconfiguration PROPERTIES VERSION ${AZ_LIBRARY_VERSION}) +generate_documentation(azure-data-appconfiguration ${AZ_LIBRARY_VERSION}) + +az_vcpkg_export( + azure-data-appconfiguration + DATA_APPCONFIGURATION + "azure/data/appconfiguration/dll_import_export.hpp" + ) + +az_rtti_setup( + azure-data-appconfiguration + DATA_APPCONFIGURATION + "azure/data/appconfiguration/rtti.hpp" +) + +if(BUILD_TESTING) + if (NOT AZ_ALL_LIBRARIES OR FETCH_SOURCE_DEPS) + include(AddGoogleTest) + enable_testing () + endif() + + # tests + add_subdirectory(test/ut) +endif() diff --git a/sdk/appconfiguration/azure-data-appconfiguration/NOTICE.txt b/sdk/appconfiguration/azure-data-appconfiguration/NOTICE.txt new file mode 100644 index 000000000..d798dc7b4 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/NOTICE.txt @@ -0,0 +1,32 @@ +azure-data-appconfiguration + +NOTICES AND INFORMATION +Do Not Translate or Localize + +This software incorporates material from third parties. Microsoft makes certain +open source code available at https://3rdpartysource.microsoft.com, or you may +send a check or money order for US $5.00, including the product name, the open +source component name, and version number, to: + +Source Code Compliance Team +Microsoft Corporation +One Microsoft Way +Redmond, WA 98052 +USA + +Notwithstanding any other terms, you may reverse engineer this software to the +extent required to debug changes to any libraries licensed under the GNU Lesser +General Public License. + +------------------------------------------------------------------------------ + +Azure SDK for C++ uses third-party libraries or other resources that may be +distributed under licenses different than the Azure SDK for C++ software. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: + + azcppsdkhelp@microsoft.com + +The attached notices are provided for information only. + diff --git a/sdk/appconfiguration/azure-data-appconfiguration/README.md b/sdk/appconfiguration/azure-data-appconfiguration/README.md new file mode 100644 index 000000000..f091c67a8 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/README.md @@ -0,0 +1,66 @@ +# Azure App Configuration Package client library for C++ + +## Getting started + +### Prerequisites +- [vcpkg](https://learn.microsoft.com/vcpkg/get_started/overview) for package acquisition and dependency management. +- [CMake](https://cmake.org/download/) for project build. +- An [Azure subscription][azure_sub]. +- An existing Azure App Configuration store. If you need to create an Azure App Configuration store, you can use the Azure Portal or [Azure CLI][azure_cli]. + +### Install the package + +## Key concepts + +Bullet point list of your library's main concepts. + +# Examples + +Examples of some of the key concepts for your library. + +## Troubleshooting + +Running into issues? This section should contain details as to what to do there. + +## Next steps + +More sample code should go here, along with links out to the appropriate example tests. + +## Contributing +For details on contributing to this repository, see the [contributing guide][azure_sdk_for_cpp_contributing]. + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +### Additional Helpful Links for Contributors +Many people all over the world have helped make this project better. You'll want to check out: + +* [What are some good first issues for new contributors to the repo?](https://github.com/azure/azure-sdk-for-cpp/issues?q=is%3Aopen+is%3Aissue+label%3A%22up+for+grabs%22) +* [How to build and test your change][azure_sdk_for_cpp_contributing_developer_guide] +* [How you can make a change happen!][azure_sdk_for_cpp_contributing_pull_requests] +* Frequently Asked Questions (FAQ) and Conceptual Topics in the detailed [Azure SDK for C++ wiki](https://github.com/azure/azure-sdk-for-cpp/wiki). + + +### Reporting security issues and security bugs + +Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) . You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the [Security TechCenter](https://www.microsoft.com/msrc/faqs-report-an-issue). + +### License + +Azure SDK for C++ is licensed under the [MIT](https://github.com/Azure/azure-sdk-for-cpp/blob/main/LICENSE.txt) license. + + +[azure_sdk_for_cpp_contributing]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md +[azure_sdk_for_cpp_contributing_developer_guide]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#developer-guide +[azure_sdk_for_cpp_contributing_pull_requests]: https://github.com/Azure/azure-sdk-for-cpp/blob/main/CONTRIBUTING.md#pull-requests +[azure_cli]: https://docs.microsoft.com/cli/azure +[azure_sub]: https://azure.microsoft.com/free/ diff --git a/sdk/appconfiguration/azure-data-appconfiguration/cgmanifest.json b/sdk/appconfiguration/azure-data-appconfiguration/cgmanifest.json new file mode 100644 index 000000000..1b872bc72 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/cgmanifest.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json.schemastore.org/component-detection-manifest.json", + "Registrations": [ + { + "Component": { + "Type": "git", + "git": { + "RepositoryUrl": "https://github.com/google/googletest", + "CommitHash": "703bd9caab50b139428cea1aaff9974ebee5742e" + } + }, + "DevelopmentDependency": true + }, + { + "Component": { + "Type": "other", + "Other": { + "Name": "clang-format", + "Version": "9.0.0-2", + "DownloadUrl": "https://ubuntu.pkgs.org/18.04/ubuntu-updates-universe-amd64/clang-format-9_9-2~ubuntu18.04.2_amd64.deb.html" + } + }, + "DevelopmentDependency": true + }, + { + "Component": { + "Type": "other", + "Other": { + "Name": "doxygen", + "Version": "1.8.20", + "DownloadUrl": "http://doxygen.nl/files/doxygen-1.8.20-setup.exe" + } + }, + "DevelopmentDependency": true + } + ] +} diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/ApiViewSettings.json b/sdk/appconfiguration/azure-data-appconfiguration/inc/ApiViewSettings.json new file mode 100644 index 000000000..7ab46bedd --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/ApiViewSettings.json @@ -0,0 +1,18 @@ +{ + "sourceFilesToProcess": null, + "sourceFilesToSkip": [ + ], + "additionalIncludeDirectories": [ + "../../../core/azure-core/inc" + ], + "additionalCompilerSwitches": [ + "-D_ALLOW_COMPILER_AND_STL_VERSION_MISMATCH" + ], + "allowInternal": false, + "includeDetail": false, + "includePrivate": false, + "filterNamespace": "Azure::Data::AppConfiguration", + "reviewName": "Azure Data AppConfiguration Review", + "serviceName": "Azure App Configuration", + "packageName": "azure-data-appconfiguration-cpp" +} diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration.hpp new file mode 100644 index 000000000..f9c73ad48 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration.hpp @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @brief Includes all public headers from Azure App Configuration SDK library. + * + */ + +#pragma once + +#include "azure/data/appconfiguration/configuration_client.hpp" +#include "azure/data/appconfiguration/configuration_client_models.hpp" +#include "azure/data/appconfiguration/configuration_client_options.hpp" +#include "azure/data/appconfiguration/dll_import_export.hpp" +#include "azure/data/appconfiguration/rtti.hpp" diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client.hpp new file mode 100644 index 000000000..f39a9c79c --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client.hpp @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "configuration_client_models.hpp" +#include "configuration_client_options.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Data { namespace AppConfiguration { + class ConfigurationClient final { + public: + explicit ConfigurationClient( + std::string const& url, + std::shared_ptr const& credential, + ConfigurationClientOptions options = {}); + + std::string GetUrl() const; + + GetKeysPagedResponse GetKeys( + std::string const& accept, + GetKeysOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckKeys( + CheckKeysOptions const& options = {}, + Core::Context const& context = {}); + + GetKeyValuesPagedResponse GetKeyValues( + std::string const& accept, + GetKeyValuesOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckKeyValues( + CheckKeyValuesOptions const& options = {}, + Core::Context const& context = {}); + + Response GetKeyValue( + std::string const& key, + std::string const& accept, + GetKeyValueOptions const& options = {}, + Core::Context const& context = {}); + + Response PutKeyValue( + PutKeyValueRequestContentType const& contentType, + std::string const& key, + std::string const& accept, + PutKeyValueOptions const& options = {}, + Core::Context const& context = {}); + + Response DeleteKeyValue( + std::string const& key, + std::string const& accept, + DeleteKeyValueOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckKeyValue( + std::string const& key, + CheckKeyValueOptions const& options = {}, + Core::Context const& context = {}); + + GetSnapshotsPagedResponse GetSnapshots( + std::string const& accept, + GetSnapshotsOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckSnapshots( + CheckSnapshotsOptions const& options = {}, + Core::Context const& context = {}); + + Response GetSnapshot( + std::string const& name, + std::string const& accept, + GetSnapshotOptions const& options = {}, + Core::Context const& context = {}); + + Response GetOperationDetails( + std::string const& snapshot, + GetOperationDetailsOptions const& options = {}, + Core::Context const& context = {}); + + Response CreateSnapshot( + CreateSnapshotRequestContentType const& contentType, + std::string const& name, + std::string const& accept, + Snapshot const& entity, + CreateSnapshotOptions const& options = {}, + Core::Context const& context = {}); + + Response UpdateSnapshot( + UpdateSnapshotRequestContentType const& contentType, + std::string const& name, + std::string const& accept, + SnapshotUpdateParameters const& entity, + UpdateSnapshotOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckSnapshot( + std::string const& name, + CheckSnapshotOptions const& options = {}, + Core::Context const& context = {}); + + GetLabelsPagedResponse GetLabels( + std::string const& accept, + GetLabelsOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckLabels( + CheckLabelsOptions const& options = {}, + Core::Context const& context = {}); + + Response PutLock( + std::string const& key, + std::string const& accept, + PutLockOptions const& options = {}, + Core::Context const& context = {}); + + Response DeleteLock( + std::string const& key, + std::string const& accept, + DeleteLockOptions const& options = {}, + Core::Context const& context = {}); + + GetRevisionsPagedResponse GetRevisions( + std::string const& accept, + GetRevisionsOptions const& options = {}, + Core::Context const& context = {}); + + Response CheckRevisions( + CheckRevisionsOptions const& options = {}, + Core::Context const& context = {}); + + private: + std::shared_ptr m_pipeline; + Core::Url m_url; + std::string m_apiVersion; + }; +}}} // namespace Azure::Data::AppConfiguration diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_models.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_models.hpp new file mode 100644 index 000000000..8260441fc --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_models.hpp @@ -0,0 +1,614 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "configuration_client_options.hpp" +#include "dll_import_export.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Data { namespace AppConfiguration { + class ConfigurationClient; + struct GetKeysOptions; + struct GetKeyValuesOptions; + struct GetSnapshotsOptions; + struct GetLabelsOptions; + struct GetRevisionsOptions; + + class GetKeysResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetKeysResponseContentType() = default; + + explicit GetKeysResponseContentType(std::string getKeysResponseContentType) + : ExtendableEnumeration(std::move(getKeysResponseContentType)) + { + } + + static GetKeysResponseContentType const ApplicationVndMicrosoftAppconfigKeysetJson; + static GetKeysResponseContentType const ApplicationProblemJson; + }; + + class GetKeyValuesResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetKeyValuesResponseContentType() = default; + + explicit GetKeyValuesResponseContentType(std::string getKeyValuesResponseContentType) + : ExtendableEnumeration(std::move(getKeyValuesResponseContentType)) + { + } + + static GetKeyValuesResponseContentType const ApplicationVndMicrosoftAppconfigKvsetJson; + static GetKeyValuesResponseContentType const ApplicationProblemJson; + }; + + class KeyValueFields final : public Core::_internal::ExtendableEnumeration { + public: + KeyValueFields() = default; + + explicit KeyValueFields(std::string keyValueFields) + : ExtendableEnumeration(std::move(keyValueFields)) + { + } + + static KeyValueFields const Key; + static KeyValueFields const Label; + static KeyValueFields const ContentType; + static KeyValueFields const Value; + static KeyValueFields const LastModified; + static KeyValueFields const Tags; + static KeyValueFields const Locked; + static KeyValueFields const Etag; + }; + + class PutKeyValueRequestContentType final + : public Core::_internal::ExtendableEnumeration { + public: + PutKeyValueRequestContentType() = default; + + explicit PutKeyValueRequestContentType(std::string putKeyValueRequestContentType) + : ExtendableEnumeration(std::move(putKeyValueRequestContentType)) + { + } + + static PutKeyValueRequestContentType const ApplicationVndMicrosoftAppconfigKvJson; + static PutKeyValueRequestContentType const ApplicationVndMicrosoftAppconfigKvsetJson; + static PutKeyValueRequestContentType const ApplicationJson; + static PutKeyValueRequestContentType const TextJson; + static PutKeyValueRequestContentType const ApplicationZeroZeroJson; + static PutKeyValueRequestContentType const ApplicationJsonPatchJson; + }; + + class SnapshotStatus final : public Core::_internal::ExtendableEnumeration { + public: + SnapshotStatus() = default; + + explicit SnapshotStatus(std::string snapshotStatus) + : ExtendableEnumeration(std::move(snapshotStatus)) + { + } + + static SnapshotStatus const Provisioning; + static SnapshotStatus const Ready; + static SnapshotStatus const Archived; + static SnapshotStatus const Failed; + }; + + class CompositionType final : public Core::_internal::ExtendableEnumeration { + public: + CompositionType() = default; + + explicit CompositionType(std::string compositionType) + : ExtendableEnumeration(std::move(compositionType)) + { + } + + static CompositionType const Key; + static CompositionType const KeyLabel; + }; + + class GetSnapshotsResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetSnapshotsResponseContentType() = default; + + explicit GetSnapshotsResponseContentType(std::string getSnapshotsResponseContentType) + : ExtendableEnumeration(std::move(getSnapshotsResponseContentType)) + { + } + + static GetSnapshotsResponseContentType const ApplicationVndMicrosoftAppconfigSnapshotsetJson; + static GetSnapshotsResponseContentType const ApplicationProblemJson; + }; + + class SnapshotFields final : public Core::_internal::ExtendableEnumeration { + public: + SnapshotFields() = default; + + explicit SnapshotFields(std::string snapshotFields) + : ExtendableEnumeration(std::move(snapshotFields)) + { + } + + static SnapshotFields const Name; + static SnapshotFields const Status; + static SnapshotFields const Filters; + static SnapshotFields const CompositionType; + static SnapshotFields const Created; + static SnapshotFields const Expires; + static SnapshotFields const RetentionPeriod; + static SnapshotFields const Size; + static SnapshotFields const ItemsCount; + static SnapshotFields const Tags; + static SnapshotFields const Etag; + }; + + class GetSnapshotResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetSnapshotResponseContentType() = default; + + explicit GetSnapshotResponseContentType(std::string getSnapshotResponseContentType) + : ExtendableEnumeration(std::move(getSnapshotResponseContentType)) + { + } + + static GetSnapshotResponseContentType const ApplicationVndMicrosoftAppconfigSnapshotJson; + static GetSnapshotResponseContentType const ApplicationProblemJson; + }; + + class OperationState final : public Core::_internal::ExtendableEnumeration { + public: + OperationState() = default; + + explicit OperationState(std::string operationState) + : ExtendableEnumeration(std::move(operationState)) + { + } + + static OperationState const NotStarted; + static OperationState const Running; + static OperationState const Succeeded; + static OperationState const Failed; + static OperationState const Canceled; + }; + + class CreateSnapshotResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + CreateSnapshotResponseContentType() = default; + + explicit CreateSnapshotResponseContentType(std::string createSnapshotResponseContentType) + : ExtendableEnumeration(std::move(createSnapshotResponseContentType)) + { + } + + static CreateSnapshotResponseContentType const ApplicationVndMicrosoftAppconfigSnapshotJson; + static CreateSnapshotResponseContentType const ApplicationProblemJson; + }; + + class CreateSnapshotRequestContentType final + : public Core::_internal::ExtendableEnumeration { + public: + CreateSnapshotRequestContentType() = default; + + explicit CreateSnapshotRequestContentType(std::string createSnapshotRequestContentType) + : ExtendableEnumeration(std::move(createSnapshotRequestContentType)) + { + } + + static CreateSnapshotRequestContentType const ApplicationVndMicrosoftAppconfigSnapshotJson; + static CreateSnapshotRequestContentType const ApplicationJson; + }; + + class UpdateSnapshotResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + UpdateSnapshotResponseContentType() = default; + + explicit UpdateSnapshotResponseContentType(std::string updateSnapshotResponseContentType) + : ExtendableEnumeration(std::move(updateSnapshotResponseContentType)) + { + } + + static UpdateSnapshotResponseContentType const ApplicationVndMicrosoftAppconfigSnapshotJson; + static UpdateSnapshotResponseContentType const ApplicationProblemJson; + }; + + class UpdateSnapshotRequestContentType final + : public Core::_internal::ExtendableEnumeration { + public: + UpdateSnapshotRequestContentType() = default; + + explicit UpdateSnapshotRequestContentType(std::string updateSnapshotRequestContentType) + : ExtendableEnumeration(std::move(updateSnapshotRequestContentType)) + { + } + + static UpdateSnapshotRequestContentType const ApplicationMergePatchJson; + static UpdateSnapshotRequestContentType const ApplicationJson; + }; + + class GetLabelsResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetLabelsResponseContentType() = default; + + explicit GetLabelsResponseContentType(std::string getLabelsResponseContentType) + : ExtendableEnumeration(std::move(getLabelsResponseContentType)) + { + } + + static GetLabelsResponseContentType const ApplicationVndMicrosoftAppconfigLabelsetJson; + static GetLabelsResponseContentType const ApplicationProblemJson; + }; + + class LabelFields final : public Core::_internal::ExtendableEnumeration { + public: + LabelFields() = default; + + explicit LabelFields(std::string labelFields) : ExtendableEnumeration(std::move(labelFields)) {} + + static LabelFields const Name; + }; + + class GetRevisionsResponseContentType final + : public Core::_internal::ExtendableEnumeration { + public: + GetRevisionsResponseContentType() = default; + + explicit GetRevisionsResponseContentType(std::string getRevisionsResponseContentType) + : ExtendableEnumeration(std::move(getRevisionsResponseContentType)) + { + } + + static GetRevisionsResponseContentType const ApplicationVndMicrosoftAppconfigKvsetJson; + static GetRevisionsResponseContentType const ApplicationProblemJson; + }; + + struct Key final + { + std::string Name; + }; + + struct CheckKeysResult final + { + std::string SyncToken; + }; + + struct KeyValue final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + }; + + struct CheckKeyValuesResult final + { + std::string SyncToken; + std::string ETag; + }; + + struct GetKeyValueResult final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + Core::Uuid XMsClientRequestId{}; + std::string SyncToken; + std::string ETag; + }; + + struct PutKeyValueResult final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + std::string SyncToken; + std::string ETag; + }; + + struct DeleteKeyValueResult final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + std::string SyncToken; + std::string ETag; + }; + + struct CheckKeyValueResult final + { + std::string SyncToken; + std::string ETag; + }; + + struct KeyValueFilter final + { + std::string Key; + Nullable Label; + Nullable> Tags; + }; + + struct Snapshot final + { + std::string Name; + Nullable Status; + std::vector Filters; + Nullable CompositionType; + Nullable Created; + Nullable Expires; + Nullable RetentionPeriod; + Nullable Size; + Nullable ItemsCount; + Nullable> Tags; + Nullable Etag; + }; + + struct CheckSnapshotsResult final + { + std::string SyncToken; + }; + + struct GetSnapshotResult final + { + std::string Name; + Nullable Status; + std::vector Filters; + Nullable CompositionType; + Nullable Created; + Nullable Expires; + Nullable RetentionPeriod; + Nullable Size; + Nullable ItemsCount; + Nullable> Tags; + Nullable Etag; + std::string SyncToken; + std::string ETag; + std::string Link; + Core::Uuid XMsClientRequestId{}; + GetSnapshotResponseContentType ContentType; + }; + + struct InnerError final + { + Nullable Code; + std::unique_ptr Innererror; + }; + + struct Error final + { + std::string Code; + std::string Message; + Nullable Target; + Nullable> Details; + InnerError Innererror; + }; + + struct OperationDetails final + { + std::string Id; + OperationState Status; + AppConfiguration::Error Error; + }; + + struct CreateSnapshotResult final + { + std::string Name; + Nullable Status; + std::vector Filters; + Nullable CompositionType; + Nullable Created; + Nullable Expires; + Nullable RetentionPeriod; + Nullable Size; + Nullable ItemsCount; + Nullable> Tags; + Nullable Etag; + std::string SyncToken; + std::string ETag; + std::string Link; + Core::Url OperationLocation; + CreateSnapshotResponseContentType ContentType; + }; + + struct UpdateSnapshotResult final + { + std::string Name; + Nullable Status; + std::vector Filters; + Nullable CompositionType; + Nullable Created; + Nullable Expires; + Nullable RetentionPeriod; + Nullable Size; + Nullable ItemsCount; + Nullable> Tags; + Nullable Etag; + std::string SyncToken; + std::string ETag; + std::string Link; + UpdateSnapshotResponseContentType ContentType; + }; + + struct SnapshotUpdateParameters final + { + Nullable Status; + }; + + struct CheckSnapshotResult final + { + std::string SyncToken; + std::string ETag; + std::string Link; + }; + + struct Label final + { + Nullable Name; + }; + + struct CheckLabelsResult final + { + std::string SyncToken; + }; + + struct PutLockResult final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + std::string SyncToken; + std::string ETag; + }; + + struct DeleteLockResult final + { + std::string Key; + Nullable Label; + Nullable ContentType; + Nullable Value; + Nullable LastModified; + Nullable> Tags; + Nullable Locked; + Nullable Etag; + std::string SyncToken; + std::string ETag; + }; + + struct CheckRevisionsResult final + { + std::string SyncToken; + std::string ETag; + }; + + class GetKeysPagedResponse final : public Core::PagedResponse { + friend class ConfigurationClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_accept; + GetKeysOptions m_options; + + void OnNextPage(Core::Context const& context); + + public: + Nullable> Items; + std::string SyncToken; + GetKeysResponseContentType ContentType; + }; + + class GetKeyValuesPagedResponse final : public Core::PagedResponse { + friend class ConfigurationClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_accept; + GetKeyValuesOptions m_options; + + void OnNextPage(Core::Context const& context); + + public: + Nullable> Items; + Nullable Etag; + std::string SyncToken; + std::string ETag; + GetKeyValuesResponseContentType ContentType; + }; + + class GetSnapshotsPagedResponse final : public Core::PagedResponse { + friend class ConfigurationClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_accept; + GetSnapshotsOptions m_options; + + void OnNextPage(Core::Context const& context); + + public: + Nullable> Items; + std::string SyncToken; + GetSnapshotsResponseContentType ContentType; + }; + + class GetLabelsPagedResponse final : public Core::PagedResponse { + friend class ConfigurationClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_accept; + GetLabelsOptions m_options; + + void OnNextPage(Core::Context const& context); + + public: + Nullable> Items; + std::string SyncToken; + GetLabelsResponseContentType ContentType; + }; + + class GetRevisionsPagedResponse final : public Core::PagedResponse { + friend class ConfigurationClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_accept; + GetRevisionsOptions m_options; + + void OnNextPage(Core::Context const& context); + + public: + Nullable> Items; + Nullable Etag; + std::string SyncToken; + std::string ETag; + GetRevisionsResponseContentType ContentType; + }; +}}} // namespace Azure::Data::AppConfiguration diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_options.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_options.hpp new file mode 100644 index 000000000..b8652d4a5 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/configuration_client_options.hpp @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "configuration_client_models.hpp" +#include "dll_import_export.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Data { namespace AppConfiguration { + class KeyValueFields; + struct KeyValue; + class SnapshotFields; + class SnapshotStatus; + class LabelFields; + + struct ConfigurationClientOptions final : public Azure::Core::_internal::ClientOptions + { + std::string ApiVersion = "2023-11-01"; + }; + + struct GetKeysOptions final + { + std::string NextPageToken; + std::string Name; + std::string After; + std::string SyncToken; + std::string AcceptDatetime; + }; + + struct CheckKeysOptions final + { + std::string Name; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetKeyValuesOptions final + { + std::string NextPageToken; + std::string Key; + std::string Label; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + std::string Snapshot; + std::string IfMatch; + std::string IfNoneMatch; + std::vector Tags; + }; + + struct CheckKeyValuesOptions final + { + std::string Key; + std::string Label; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + std::string Snapshot; + std::string IfMatch; + std::string IfNoneMatch; + std::vector Tags; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetKeyValueOptions final + { + std::string Label; + std::vector Select; + std::string SyncToken; + std::string AcceptDatetime; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct PutKeyValueOptions final + { + std::string Label; + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + // KeyValue Entity; TODO: Implement KeyValue entity + }; + + struct DeleteKeyValueOptions final + { + std::string Label; + std::string SyncToken; + std::string IfMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct CheckKeyValueOptions final + { + std::string Label; + std::string SyncToken; + std::string AcceptDatetime; + std::string IfMatch; + std::string IfNoneMatch; + std::vector Select; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetSnapshotsOptions final + { + std::string NextPageToken; + std::string Name; + std::string After; + std::vector Select; + std::vector Status; + std::string SyncToken; + }; + + struct CheckSnapshotsOptions final + { + std::string SyncToken; + std::string After; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetSnapshotOptions final + { + std::vector Select; + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetOperationDetailsOptions final + { + Core::Uuid XMsClientRequestId{}; + }; + + struct CreateSnapshotOptions final + { + std::string SyncToken; + }; + + struct UpdateSnapshotOptions final + { + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct CheckSnapshotOptions final + { + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetLabelsOptions final + { + std::string NextPageToken; + std::string Name; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + Core::Uuid XMsClientRequestId{}; + }; + + struct CheckLabelsOptions final + { + std::string Name; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + Core::Uuid XMsClientRequestId{}; + }; + + struct PutLockOptions final + { + std::string Label; + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct DeleteLockOptions final + { + std::string Label; + std::string SyncToken; + std::string IfMatch; + std::string IfNoneMatch; + Core::Uuid XMsClientRequestId{}; + }; + + struct GetRevisionsOptions final + { + std::string NextPageToken; + std::string Key; + std::string Label; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + std::vector Tags; + Core::Uuid XMsClientRequestId{}; + }; + + struct CheckRevisionsOptions final + { + std::string Key; + std::string Label; + std::string SyncToken; + std::string After; + std::string AcceptDatetime; + std::vector Select; + std::vector Tags; + Core::Uuid XMsClientRequestId{}; + }; +}}} // namespace Azure::Data::AppConfiguration diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/dll_import_export.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/dll_import_export.hpp new file mode 100644 index 000000000..d9dedb3c7 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/dll_import_export.hpp @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @file + * @brief DLL export macro. + */ + +// For explanation, see the comment in azure/core/dll_import_export.hpp + +#pragma once + +/** + * @def AZ_DATA_APPCONFIGURATION_DLLEXPORT + * @brief Applies DLL export attribute, when applicable. + * @note See https://docs.microsoft.com/cpp/cpp/dllexport-dllimport?view=msvc-160. + */ + +#if defined(AZ_DATA_APPCONFIGURATION_DLL) \ + || (0 /*@AZ_DATA_APPCONFIGURATION_DLL_INSTALLED_AS_PACKAGE@*/) +#define AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL 1 +#else +#define AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL 0 +#endif + +#if AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL +#if defined(_MSC_VER) +#if defined(AZ_DATA_APPCONFIGURATION_BEING_BUILT) +#define AZ_DATA_APPCONFIGURATION_DLLEXPORT __declspec(dllexport) +#else // !defined(AZ_DATA_APPCONFIGURATION_BEING_BUILT) +#define AZ_DATA_APPCONFIGURATION_DLLEXPORT __declspec(dllimport) +#endif // AZ_DATA_APPCONFIGURATION_BEING_BUILT +#else // !defined(_MSC_VER) +#define AZ_DATA_APPCONFIGURATION_DLLEXPORT +#endif // _MSC_VER +#else // !AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL +#define AZ_DATA_APPCONFIGURATION_DLLEXPORT +#endif // AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL + +#undef AZ_DATA_APPCONFIGURATION_BUILT_AS_DLL diff --git a/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/rtti.hpp b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/rtti.hpp new file mode 100644 index 000000000..839da70dc --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/inc/azure/data/appconfiguration/rtti.hpp @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * @file + * @brief Run-time type info enable or disable. + * + * @details When RTTI is enabled, defines a macro `AZ_DATA_APPCONFIGURATION_RTTI`. When + * the macro is not defined, RTTI is disabled. + * + * @details Each library has this header file. These headers are being configured by + * `az_rtti_setup()` CMake macro. CMake install will patch this file during installation, depending + * on the build flags. + */ + +#pragma once + +/** + * @def AZ_DATA_APPCONFIGURATION_RTTI + * @brief A macro indicating whether the code is built with RTTI or not. + * + * @details `AZ_RTTI` could be defined while building the Azure SDK with CMake, however, after + * the build is completed, that information is not preserved for the code that consumes Azure SDK + * headers, unless the code that consumes the SDK is the part of the same build process. To address + * this issue, CMake install would patch the header it places in the installation directory, so that + * condition: + * `#if defined(AZ_RTTI) || (0)` + * becomes, effectively, + * `#if defined(AZ_RTTI) || (0 + 1)` + * when the library was built with RTTI support, and will make no changes to the + * condition when it was not. + */ + +#if defined(AZ_RTTI) || (0 /*@AZ_DATA_APPCONFIGURATION_RTTI@*/) +#define AZ_DATA_APPCONFIGURATION_RTTI +#endif diff --git a/sdk/appconfiguration/azure-data-appconfiguration/src/configuration_client.cpp b/sdk/appconfiguration/azure-data-appconfiguration/src/configuration_client.cpp new file mode 100644 index 000000000..4a36d5513 --- /dev/null +++ b/sdk/appconfiguration/azure-data-appconfiguration/src/configuration_client.cpp @@ -0,0 +1,2318 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "azure/data/appconfiguration/configuration_client.hpp" + +#include "private/package_version.hpp" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace Azure::Data::AppConfiguration; +using namespace Azure::Data::AppConfiguration::_detail; + +GetKeysResponseContentType const + GetKeysResponseContentType::ApplicationVndMicrosoftAppconfigKeysetJson{ + "application/vnd.microsoft.appconfig.keyset+json"}; +GetKeysResponseContentType const GetKeysResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +GetKeyValuesResponseContentType const + GetKeyValuesResponseContentType::ApplicationVndMicrosoftAppconfigKvsetJson{ + "application/vnd.microsoft.appconfig.kvset+json"}; +GetKeyValuesResponseContentType const GetKeyValuesResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +KeyValueFields const KeyValueFields::Key{"key"}; +KeyValueFields const KeyValueFields::Label{"label"}; +KeyValueFields const KeyValueFields::ContentType{"content_type"}; +KeyValueFields const KeyValueFields::Value{"value"}; +KeyValueFields const KeyValueFields::LastModified{"last_modified"}; +KeyValueFields const KeyValueFields::Tags{"tags"}; +KeyValueFields const KeyValueFields::Locked{"locked"}; +KeyValueFields const KeyValueFields::Etag{"etag"}; + +PutKeyValueRequestContentType const + PutKeyValueRequestContentType::ApplicationVndMicrosoftAppconfigKvJson{ + "application/vnd.microsoft.appconfig.kv+json"}; +PutKeyValueRequestContentType const + PutKeyValueRequestContentType::ApplicationVndMicrosoftAppconfigKvsetJson{ + "application/vnd.microsoft.appconfig.kvset+json"}; +PutKeyValueRequestContentType const PutKeyValueRequestContentType::ApplicationJson{ + "application/json"}; +PutKeyValueRequestContentType const PutKeyValueRequestContentType::TextJson{"text/json"}; +PutKeyValueRequestContentType const PutKeyValueRequestContentType::ApplicationZeroZeroJson{ + "application/*+json"}; +PutKeyValueRequestContentType const PutKeyValueRequestContentType::ApplicationJsonPatchJson{ + "application/json-patch+json"}; + +SnapshotStatus const SnapshotStatus::Provisioning{"provisioning"}; +SnapshotStatus const SnapshotStatus::Ready{"ready"}; +SnapshotStatus const SnapshotStatus::Archived{"archived"}; +SnapshotStatus const SnapshotStatus::Failed{"failed"}; + +CompositionType const CompositionType::Key{"key"}; +CompositionType const CompositionType::KeyLabel{"key_label"}; + +GetSnapshotsResponseContentType const + GetSnapshotsResponseContentType::ApplicationVndMicrosoftAppconfigSnapshotsetJson{ + "application/vnd.microsoft.appconfig.snapshotset+json"}; +GetSnapshotsResponseContentType const GetSnapshotsResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +SnapshotFields const SnapshotFields::Name{"name"}; +SnapshotFields const SnapshotFields::Status{"status"}; +SnapshotFields const SnapshotFields::Filters{"filters"}; +SnapshotFields const SnapshotFields::CompositionType{"composition_type"}; +SnapshotFields const SnapshotFields::Created{"created"}; +SnapshotFields const SnapshotFields::Expires{"expires"}; +SnapshotFields const SnapshotFields::RetentionPeriod{"retention_period"}; +SnapshotFields const SnapshotFields::Size{"size"}; +SnapshotFields const SnapshotFields::ItemsCount{"items_count"}; +SnapshotFields const SnapshotFields::Tags{"tags"}; +SnapshotFields const SnapshotFields::Etag{"etag"}; + +GetSnapshotResponseContentType const + GetSnapshotResponseContentType::ApplicationVndMicrosoftAppconfigSnapshotJson{ + "application/vnd.microsoft.appconfig.snapshot+json"}; +GetSnapshotResponseContentType const GetSnapshotResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +OperationState const OperationState::NotStarted{"NotStarted"}; +OperationState const OperationState::Running{"Running"}; +OperationState const OperationState::Succeeded{"Succeeded"}; +OperationState const OperationState::Failed{"Failed"}; +OperationState const OperationState::Canceled{"Canceled"}; + +CreateSnapshotResponseContentType const + CreateSnapshotResponseContentType::ApplicationVndMicrosoftAppconfigSnapshotJson{ + "application/vnd.microsoft.appconfig.snapshot+json"}; +CreateSnapshotResponseContentType const CreateSnapshotResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +CreateSnapshotRequestContentType const + CreateSnapshotRequestContentType::ApplicationVndMicrosoftAppconfigSnapshotJson{ + "application/vnd.microsoft.appconfig.snapshot+json"}; +CreateSnapshotRequestContentType const CreateSnapshotRequestContentType::ApplicationJson{ + "application/json"}; + +UpdateSnapshotResponseContentType const + UpdateSnapshotResponseContentType::ApplicationVndMicrosoftAppconfigSnapshotJson{ + "application/vnd.microsoft.appconfig.snapshot+json"}; +UpdateSnapshotResponseContentType const UpdateSnapshotResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +UpdateSnapshotRequestContentType const UpdateSnapshotRequestContentType::ApplicationMergePatchJson{ + "application/merge-patch+json"}; +UpdateSnapshotRequestContentType const UpdateSnapshotRequestContentType::ApplicationJson{ + "application/json"}; + +GetLabelsResponseContentType const + GetLabelsResponseContentType::ApplicationVndMicrosoftAppconfigLabelsetJson{ + "application/vnd.microsoft.appconfig.labelset+json"}; +GetLabelsResponseContentType const GetLabelsResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +LabelFields const LabelFields::Name{"name"}; + +GetRevisionsResponseContentType const + GetRevisionsResponseContentType::ApplicationVndMicrosoftAppconfigKvsetJson{ + "application/vnd.microsoft.appconfig.kvset+json"}; +GetRevisionsResponseContentType const GetRevisionsResponseContentType::ApplicationProblemJson{ + "application/problem+json"}; + +void GetKeysPagedResponse::OnNextPage(Core::Context const& context) +{ + auto const pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetKeys(this->m_accept, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} + +void GetKeyValuesPagedResponse::OnNextPage(Core::Context const& context) +{ + auto const pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetKeyValues(this->m_accept, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} + +void GetSnapshotsPagedResponse::OnNextPage(Core::Context const& context) +{ + auto const pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetSnapshots(this->m_accept, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} + +void GetLabelsPagedResponse::OnNextPage(Core::Context const& context) +{ + auto const pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetLabels(this->m_accept, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} + +void GetRevisionsPagedResponse::OnNextPage(Core::Context const& context) +{ + auto const pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetRevisions(this->m_accept, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} + +ConfigurationClient::ConfigurationClient( + std::string const& url, + std::shared_ptr const& credential, + ConfigurationClientOptions options) + : m_url(url), m_apiVersion(options.ApiVersion) +{ + std::vector> perRetryPolicies; + { + Core::Credentials::TokenRequestContext tokenRequestContext; + tokenRequestContext.Scopes = {"https://azconfig.io/.default"}; + perRetryPolicies.emplace_back( + std::make_unique( + credential, tokenRequestContext)); + } + + m_pipeline.reset(new Core::Http::_internal::HttpPipeline( + {}, "data-appconfiguration", PackageVersion::ToString(), std::move(perRetryPolicies), {})); +} + +std::string ConfigurationClient::GetUrl() const { return m_url.GetAbsoluteUrl(); } + +GetKeysPagedResponse ConfigurationClient::GetKeys( + std::string const& accept, + GetKeysOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("keys"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("name", Core::Url::Encode(options.Name)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + url.SetPort(m_url.GetPort()); + } + else if (!options.NextPageToken.empty()) + { + url.SetPath( + options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) : options.NextPageToken); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetKeysPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_accept = accept; + response.m_options = options; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("@nextLink") && !jsonRoot["@nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["@nextLink"].get(); + } + + if (jsonRoot.contains("items")) + { + response.Items = std::vector{}; + + for (auto const& jsonItem : jsonRoot["items"]) + { + Key vectorItem{}; + + vectorItem.Name = jsonItem["name"].get(); + + response.Items.Value().emplace_back(std::move(vectorItem)); + } + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ContentType = GetKeysResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + response.RawResponse = std::move(rawResponse); + + return response; +} + +Azure::Response ConfigurationClient::CheckKeys( + CheckKeysOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("keys"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("name", Core::Url::Encode(options.Name)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + Core::Http::Request request(Core::Http::HttpMethod::Head, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + CheckKeysResult response{}; + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + + return Response(std::move(response), std::move(rawResponse)); +} + +GetKeyValuesPagedResponse ConfigurationClient::GetKeyValues( + std::string const& accept, + GetKeyValuesOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("key", Core::Url::Encode(options.Key)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + url.AppendQueryParameter("snapshot", Core::Url::Encode(options.Snapshot)); + { + std::string valueStr; + for (size_t i = 0; i < options.Tags.size(); ++i) + { + if (i != 0) + { + valueStr += "&tags="; + } + + valueStr += Core::Url::Encode(options.Tags[i]); + } + + url.AppendQueryParameter("tags", valueStr); + } + + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + url.SetPort(m_url.GetPort()); + } + else if (!options.NextPageToken.empty()) + { + url.SetPath( + options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) : options.NextPageToken); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetKeyValuesPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_accept = accept; + response.m_options = options; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("@nextLink") && !jsonRoot["@nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["@nextLink"].get(); + } + + if (jsonRoot.contains("items")) + { + response.Items = std::vector{}; + + for (auto const& jsonItem : jsonRoot["items"]) + { + KeyValue vectorItem{}; + + vectorItem.Key = jsonItem["key"].get(); + + if (jsonItem.contains("label") && !jsonItem["label"].is_null()) + { + vectorItem.Label = jsonItem["label"].get(); + } + + if (jsonItem.contains("content_type") && !jsonItem["content_type"].is_null()) + { + vectorItem.ContentType = jsonItem["content_type"].get(); + } + + if (jsonItem.contains("value") && !jsonItem["value"].is_null()) + { + vectorItem.Value = jsonItem["value"].get(); + } + + if (jsonItem.contains("last_modified") && !jsonItem["last_modified"].is_null()) + { + vectorItem.LastModified = jsonItem["last_modified"].get(); + } + + if (jsonItem.contains("tags")) + { + vectorItem.Tags = std::map{}; + + for (auto const& kv : jsonItem["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + vectorItem.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonItem.contains("locked") && !jsonItem["locked"].is_null()) + { + vectorItem.Locked = jsonItem["locked"].is_string() + ? (jsonItem["locked"].get() == "true") + : jsonItem["locked"].get(); + } + + if (jsonItem.contains("etag") && !jsonItem["etag"].is_null()) + { + vectorItem.Etag = jsonItem["etag"].get(); + } + + response.Items.Value().emplace_back(std::move(vectorItem)); + } + } + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + response.ContentType + = GetKeyValuesResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + response.RawResponse = std::move(rawResponse); + + return response; +} + +Azure::Response ConfigurationClient::CheckKeyValues( + CheckKeyValuesOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("key", Core::Url::Encode(options.Key)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + url.AppendQueryParameter("snapshot", Core::Url::Encode(options.Snapshot)); + { + std::string valueStr; + for (size_t i = 0; i < options.Tags.size(); ++i) + { + if (i != 0) + { + valueStr += "&tags="; + } + + valueStr += Core::Url::Encode(options.Tags[i]); + } + + url.AppendQueryParameter("tags", valueStr); + } + + Core::Http::Request request(Core::Http::HttpMethod::Head, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + CheckKeyValuesResult response{}; + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::GetKeyValue( + std::string const& key, + std::string const& accept, + GetKeyValueOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv/"); + url.AppendPath(!key.empty() ? Core::Url::Encode(key) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetKeyValueResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Key = jsonRoot["key"].get(); + + if (jsonRoot.contains("label") && !jsonRoot["label"].is_null()) + { + response.Label = jsonRoot["label"].get(); + } + + if (jsonRoot.contains("content_type") && !jsonRoot["content_type"].is_null()) + { + response.ContentType = jsonRoot["content_type"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = jsonRoot["value"].get(); + } + + if (jsonRoot.contains("last_modified") && !jsonRoot["last_modified"].is_null()) + { + response.LastModified = jsonRoot["last_modified"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("locked") && !jsonRoot["locked"].is_null()) + { + response.Locked = jsonRoot["locked"].is_string() + ? (jsonRoot["locked"].get() == "true") + : jsonRoot["locked"].get(); + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.XMsClientRequestId + = Core::Uuid::Parse(rawResponse->GetHeaders().at("x-ms-client-request-id")); + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::PutKeyValue( + PutKeyValueRequestContentType const& contentType, + std::string const& key, + std::string const& accept, + PutKeyValueOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv/"); + url.AppendPath(!key.empty() ? Core::Url::Encode(key) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + +// TODO: Add support for KeyValue Entity +#if 0 + jsonRoot["key"] = options.Entity.Key; + + if (options.Entity.Label.HasValue()) + { + jsonRoot["label"] = options.Entity.Label.Value(); + } + + if (options.Entity.ContentType.HasValue()) + { + jsonRoot["content_type"] = options.Entity.ContentType.Value(); + } + + if (options.Entity.Value.HasValue()) + { + jsonRoot["value"] = options.Entity.Value.Value(); + } + + if (options.Entity.LastModified.HasValue()) + { + jsonRoot["last_modified"] = options.Entity.LastModified.Value(); + } + if (options.Entity.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : options.Entity.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + if (options.Entity.Locked.HasValue()) + { + jsonRoot["locked"] = options.Entity.Locked.Value(); + } + + if (options.Entity.Etag.HasValue()) + { + jsonRoot["etag"] = options.Entity.Etag.Value(); + } +#endif + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody); + + request.SetHeader("Content-Type", contentType.ToString()); + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + PutKeyValueResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Key = jsonRoot["key"].get(); + + if (jsonRoot.contains("label") && !jsonRoot["label"].is_null()) + { + response.Label = jsonRoot["label"].get(); + } + + if (jsonRoot.contains("content_type") && !jsonRoot["content_type"].is_null()) + { + response.ContentType = jsonRoot["content_type"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = jsonRoot["value"].get(); + } + + if (jsonRoot.contains("last_modified") && !jsonRoot["last_modified"].is_null()) + { + response.LastModified = jsonRoot["last_modified"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("locked") && !jsonRoot["locked"].is_null()) + { + response.Locked = jsonRoot["locked"].is_string() + ? (jsonRoot["locked"].get() == "true") + : jsonRoot["locked"].get(); + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::DeleteKeyValue( + std::string const& key, + std::string const& accept, + DeleteKeyValueOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv/"); + url.AppendPath(!key.empty() ? Core::Url::Encode(key) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + Core::Http::Request request(Core::Http::HttpMethod::Delete, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::NoContent + && httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + DeleteKeyValueResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Key = jsonRoot["key"].get(); + + if (jsonRoot.contains("label") && !jsonRoot["label"].is_null()) + { + response.Label = jsonRoot["label"].get(); + } + + if (jsonRoot.contains("content_type") && !jsonRoot["content_type"].is_null()) + { + response.ContentType = jsonRoot["content_type"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = jsonRoot["value"].get(); + } + + if (jsonRoot.contains("last_modified") && !jsonRoot["last_modified"].is_null()) + { + response.LastModified = jsonRoot["last_modified"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("locked") && !jsonRoot["locked"].is_null()) + { + response.Locked = jsonRoot["locked"].is_string() + ? (jsonRoot["locked"].get() == "true") + : jsonRoot["locked"].get(); + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::CheckKeyValue( + std::string const& key, + CheckKeyValueOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("kv/"); + url.AppendPath(!key.empty() ? Core::Url::Encode(key) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("label", Core::Url::Encode(options.Label)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + Core::Http::Request request(Core::Http::HttpMethod::Head, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + CheckKeyValueResult response{}; + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + + return Response(std::move(response), std::move(rawResponse)); +} + +GetSnapshotsPagedResponse ConfigurationClient::GetSnapshots( + std::string const& accept, + GetSnapshotsOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("name", Core::Url::Encode(options.Name)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + { + std::string valueStr; + for (size_t i = 0; i < options.Status.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Status[i].ToString()); + } + + url.AppendQueryParameter("status", valueStr); + } + + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + url.SetPort(m_url.GetPort()); + } + else if (!options.NextPageToken.empty()) + { + url.SetPath( + options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) : options.NextPageToken); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetSnapshotsPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_accept = accept; + response.m_options = options; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("@nextLink") && !jsonRoot["@nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["@nextLink"].get(); + } + + if (jsonRoot.contains("items")) + { + response.Items = std::vector{}; + + for (auto const& jsonItem : jsonRoot["items"]) + { + Snapshot vectorItem{}; + + vectorItem.Name = jsonItem["name"].get(); + + if (jsonItem.contains("status") && !jsonItem["status"].is_null()) + { + vectorItem.Status = SnapshotStatus(jsonItem["status"].get()); + } + + for (auto const& jsonItemNested : jsonItem["filters"]) + { + KeyValueFilter vecItem{}; + + vecItem.Key = jsonItemNested["key"].get(); + + if (jsonItemNested.contains("label") && !jsonItemNested["label"].is_null()) + { + vecItem.Label = jsonItemNested["label"].get(); + } + + if (jsonItemNested.contains("tags")) + { + vecItem.Tags = std::vector{}; + + for (auto const& jsonItemNestedAgain : jsonItemNested["tags"]) + { + std::string vi{}; + + vi = jsonItemNestedAgain.get(); + + vecItem.Tags.Value().emplace_back(std::move(vi)); + } + } + + vectorItem.Filters.emplace_back(std::move(vecItem)); + } + + if (jsonItem.contains("composition_type") && !jsonItem["composition_type"].is_null()) + { + vectorItem.CompositionType + = CompositionType(jsonItem["composition_type"].get()); + } + + if (jsonItem.contains("created") && !jsonItem["created"].is_null()) + { + vectorItem.Created = jsonItem["created"].get(); + } + + if (jsonItem.contains("expires") && !jsonItem["expires"].is_null()) + { + vectorItem.Expires = jsonItem["expires"].get(); + } + + if (jsonItem.contains("retention_period") && !jsonItem["retention_period"].is_null()) + { + vectorItem.RetentionPeriod = jsonItem["retention_period"].is_string() + ? std::stoll(jsonItem["retention_period"].get()) + : jsonItem["retention_period"].get(); + } + + if (jsonItem.contains("size") && !jsonItem["size"].is_null()) + { + vectorItem.Size = jsonItem["size"].is_string() + ? std::stoll(jsonItem["size"].get()) + : jsonItem["size"].get(); + } + + if (jsonItem.contains("items_count") && !jsonItem["items_count"].is_null()) + { + vectorItem.ItemsCount = jsonItem["items_count"].is_string() + ? std::stoll(jsonItem["items_count"].get()) + : jsonItem["items_count"].get(); + } + + if (jsonItem.contains("tags")) + { + vectorItem.Tags = std::map{}; + + for (auto const& kv : jsonItem["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + vectorItem.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonItem.contains("etag") && !jsonItem["etag"].is_null()) + { + vectorItem.Etag = jsonItem["etag"].get(); + } + + response.Items.Value().emplace_back(std::move(vectorItem)); + } + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ContentType + = GetSnapshotsResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + response.RawResponse = std::move(rawResponse); + + return response; +} + +Azure::Response ConfigurationClient::CheckSnapshots( + CheckSnapshotsOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + Core::Http::Request request(Core::Http::HttpMethod::Head, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + CheckSnapshotsResult response{}; + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::GetSnapshot( + std::string const& name, + std::string const& accept, + GetSnapshotOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots/"); + url.AppendPath(!name.empty() ? Core::Url::Encode(name) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetSnapshotResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Name = jsonRoot["name"].get(); + + if (jsonRoot.contains("status") && !jsonRoot["status"].is_null()) + { + response.Status = SnapshotStatus(jsonRoot["status"].get()); + } + + for (auto const& jsonItem : jsonRoot["filters"]) + { + KeyValueFilter vectorItem{}; + + vectorItem.Key = jsonItem["key"].get(); + + if (jsonItem.contains("label") && !jsonItem["label"].is_null()) + { + vectorItem.Label = jsonItem["label"].get(); + } + + if (jsonItem.contains("tags")) + { + vectorItem.Tags = std::vector{}; + + for (auto const& jsonItemNested : jsonItem["tags"]) + { + std::string vecItem{}; + + vecItem = jsonItemNested.get(); + + vectorItem.Tags.Value().emplace_back(std::move(vecItem)); + } + } + + response.Filters.emplace_back(std::move(vectorItem)); + } + + if (jsonRoot.contains("composition_type") && !jsonRoot["composition_type"].is_null()) + { + response.CompositionType = CompositionType(jsonRoot["composition_type"].get()); + } + + if (jsonRoot.contains("created") && !jsonRoot["created"].is_null()) + { + response.Created = jsonRoot["created"].get(); + } + + if (jsonRoot.contains("expires") && !jsonRoot["expires"].is_null()) + { + response.Expires = jsonRoot["expires"].get(); + } + + if (jsonRoot.contains("retention_period") && !jsonRoot["retention_period"].is_null()) + { + response.RetentionPeriod = jsonRoot["retention_period"].is_string() + ? std::stoll(jsonRoot["retention_period"].get()) + : jsonRoot["retention_period"].get(); + } + + if (jsonRoot.contains("size") && !jsonRoot["size"].is_null()) + { + response.Size = jsonRoot["size"].is_string() + ? std::stoll(jsonRoot["size"].get()) + : jsonRoot["size"].get(); + } + + if (jsonRoot.contains("items_count") && !jsonRoot["items_count"].is_null()) + { + response.ItemsCount = jsonRoot["items_count"].is_string() + ? std::stoll(jsonRoot["items_count"].get()) + : jsonRoot["items_count"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + response.Link = rawResponse->GetHeaders().at("Link"); + response.XMsClientRequestId + = Core::Uuid::Parse(rawResponse->GetHeaders().at("x-ms-client-request-id")); + response.ContentType + = GetSnapshotResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::GetOperationDetails( + std::string const& snapshot, + GetOperationDetailsOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("operations"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("snapshot", Core::Url::Encode(snapshot)); + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + OperationDetails response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Id = jsonRoot["id"].get(); + + response.Status = OperationState(jsonRoot["status"].get()); + + std::function const deserializeError + = [&](Error& error, Core::Json::_internal::json const& jsonItem) { + error.Code = jsonItem["code"].get(); + + error.Message = jsonItem["message"].get(); + + if (jsonItem.contains("target") && !jsonItem["target"].is_null()) + { + error.Target = jsonItem["target"].get(); + } + + if (jsonItem.contains("details")) + { + error.Details = std::vector{}; + + for (auto const& jsonItemNested : jsonItem["details"]) + { + Error vectorItem{}; + + deserializeError(vectorItem, jsonItemNested); + + error.Details.Value().emplace_back(std::move(vectorItem)); + } + } + + std::function const + deserializeInnerError + = [&](InnerError& innerError, Core::Json::_internal::json const& jsonItem) { + if (jsonItem.contains("code") && !jsonItem["code"].is_null()) + { + innerError.Code = jsonItem["code"].get(); + } + + std::function&, Core::Json::_internal::json const&)> const + deserializeInnerErrorPtr + = [&](std::unique_ptr& innerError, + Core::Json::_internal::json const& jsonItem) { + if (jsonItem.contains("code") && !jsonItem["code"].is_null()) + { + if (!innerError) + { + innerError = std::make_unique(); + } + + innerError->Code = jsonItem["code"].get(); + } + + deserializeInnerErrorPtr( + innerError->Innererror, jsonItem["innererror"]); + }; + deserializeInnerErrorPtr(innerError.Innererror, jsonItem["innererror"]); + }; + deserializeInnerError(error.Innererror, jsonItem["innererror"]); + }; + deserializeError(response.Error, jsonRoot["error"]); + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::CreateSnapshot( + CreateSnapshotRequestContentType const& contentType, + std::string const& name, + std::string const& accept, + Snapshot const& entity, + CreateSnapshotOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots/"); + url.AppendPath(!name.empty() ? Core::Url::Encode(name) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + + jsonRoot["name"] = entity.Name; + + if (entity.Status.HasValue()) + { + jsonRoot["status"] = entity.Status.Value().ToString(); + } + for (size_t i = 0; i < entity.Filters.size(); ++i) + { + jsonRoot["filters"][i]["key"] = entity.Filters[i].Key; + + if (entity.Filters[i].Label.HasValue()) + { + jsonRoot["filters"][i]["label"] = entity.Filters[i].Label.Value(); + } + if (entity.Filters[i].Tags.HasValue()) + { + jsonRoot["filters"][i]["tags"] = Core::Json::_internal::json::array(); + + for (size_t j = 0; j < entity.Filters[i].Tags.Value().size(); ++j) + { + jsonRoot["filters"][i]["tags"][j] = entity.Filters[i].Tags.Value()[j]; + } + } + } + + if (entity.CompositionType.HasValue()) + { + jsonRoot["composition_type"] = entity.CompositionType.Value().ToString(); + } + + if (entity.Created.HasValue()) + { + jsonRoot["created"] = entity.Created.Value(); + } + + if (entity.Expires.HasValue()) + { + jsonRoot["expires"] = entity.Expires.Value(); + } + + if (entity.RetentionPeriod.HasValue()) + { + jsonRoot["retention_period"] = entity.RetentionPeriod.Value(); + } + + if (entity.Size.HasValue()) + { + jsonRoot["size"] = entity.Size.Value(); + } + + if (entity.ItemsCount.HasValue()) + { + jsonRoot["items_count"] = entity.ItemsCount.Value(); + } + if (entity.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : entity.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + if (entity.Etag.HasValue()) + { + jsonRoot["etag"] = entity.Etag.Value(); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody); + + request.SetHeader("Content-Type", contentType.ToString()); + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Created) + { + throw Core::RequestFailedException(rawResponse); + } + + CreateSnapshotResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Name = jsonRoot["name"].get(); + + if (jsonRoot.contains("status") && !jsonRoot["status"].is_null()) + { + response.Status = SnapshotStatus(jsonRoot["status"].get()); + } + + for (auto const& jsonItem : jsonRoot["filters"]) + { + KeyValueFilter vectorItem{}; + + vectorItem.Key = jsonItem["key"].get(); + + if (jsonItem.contains("label") && !jsonItem["label"].is_null()) + { + vectorItem.Label = jsonItem["label"].get(); + } + + if (jsonItem.contains("tags")) + { + vectorItem.Tags = std::vector{}; + + for (auto const& jsonItemNested : jsonItem["tags"]) + { + std::string vecItem{}; + + vecItem = jsonItemNested.get(); + + vectorItem.Tags.Value().emplace_back(std::move(vecItem)); + } + } + + response.Filters.emplace_back(std::move(vectorItem)); + } + + if (jsonRoot.contains("composition_type") && !jsonRoot["composition_type"].is_null()) + { + response.CompositionType = CompositionType(jsonRoot["composition_type"].get()); + } + + if (jsonRoot.contains("created") && !jsonRoot["created"].is_null()) + { + response.Created = jsonRoot["created"].get(); + } + + if (jsonRoot.contains("expires") && !jsonRoot["expires"].is_null()) + { + response.Expires = jsonRoot["expires"].get(); + } + + if (jsonRoot.contains("retention_period") && !jsonRoot["retention_period"].is_null()) + { + response.RetentionPeriod = jsonRoot["retention_period"].is_string() + ? std::stoll(jsonRoot["retention_period"].get()) + : jsonRoot["retention_period"].get(); + } + + if (jsonRoot.contains("size") && !jsonRoot["size"].is_null()) + { + response.Size = jsonRoot["size"].is_string() + ? std::stoll(jsonRoot["size"].get()) + : jsonRoot["size"].get(); + } + + if (jsonRoot.contains("items_count") && !jsonRoot["items_count"].is_null()) + { + response.ItemsCount = jsonRoot["items_count"].is_string() + ? std::stoll(jsonRoot["items_count"].get()) + : jsonRoot["items_count"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + response.Link = rawResponse->GetHeaders().at("Link"); + response.OperationLocation = Core::Url(rawResponse->GetHeaders().at("Operation-Location")); + response.ContentType + = CreateSnapshotResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::UpdateSnapshot( + UpdateSnapshotRequestContentType const& contentType, + std::string const& name, + std::string const& accept, + SnapshotUpdateParameters const& entity, + UpdateSnapshotOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots/"); + url.AppendPath(!name.empty() ? Core::Url::Encode(name) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + + if (entity.Status.HasValue()) + { + jsonRoot["status"] = entity.Status.Value().ToString(); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody); + + request.SetHeader("Content-Type", contentType.ToString()); + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + UpdateSnapshotResult response{}; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Name = jsonRoot["name"].get(); + + if (jsonRoot.contains("status") && !jsonRoot["status"].is_null()) + { + response.Status = SnapshotStatus(jsonRoot["status"].get()); + } + + for (auto const& jsonItem : jsonRoot["filters"]) + { + KeyValueFilter vectorItem{}; + + vectorItem.Key = jsonItem["key"].get(); + + if (jsonItem.contains("label") && !jsonItem["label"].is_null()) + { + vectorItem.Label = jsonItem["label"].get(); + } + + if (jsonItem.contains("tags")) + { + vectorItem.Tags = std::vector{}; + + for (auto const& jsonItemNested : jsonItem["tags"]) + { + std::string vecItem{}; + + vecItem = jsonItemNested.get(); + + vectorItem.Tags.Value().emplace_back(std::move(vecItem)); + } + } + + response.Filters.emplace_back(std::move(vectorItem)); + } + + if (jsonRoot.contains("composition_type") && !jsonRoot["composition_type"].is_null()) + { + response.CompositionType = CompositionType(jsonRoot["composition_type"].get()); + } + + if (jsonRoot.contains("created") && !jsonRoot["created"].is_null()) + { + response.Created = jsonRoot["created"].get(); + } + + if (jsonRoot.contains("expires") && !jsonRoot["expires"].is_null()) + { + response.Expires = jsonRoot["expires"].get(); + } + + if (jsonRoot.contains("retention_period") && !jsonRoot["retention_period"].is_null()) + { + response.RetentionPeriod = jsonRoot["retention_period"].is_string() + ? std::stoll(jsonRoot["retention_period"].get()) + : jsonRoot["retention_period"].get(); + } + + if (jsonRoot.contains("size") && !jsonRoot["size"].is_null()) + { + response.Size = jsonRoot["size"].is_string() + ? std::stoll(jsonRoot["size"].get()) + : jsonRoot["size"].get(); + } + + if (jsonRoot.contains("items_count") && !jsonRoot["items_count"].is_null()) + { + response.ItemsCount = jsonRoot["items_count"].is_string() + ? std::stoll(jsonRoot["items_count"].get()) + : jsonRoot["items_count"].get(); + } + + if (jsonRoot.contains("tags")) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("etag") && !jsonRoot["etag"].is_null()) + { + response.Etag = jsonRoot["etag"].get(); + } + } + } + + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + response.Link = rawResponse->GetHeaders().at("Link"); + response.ContentType + = UpdateSnapshotResponseContentType(rawResponse->GetHeaders().at("Content-Type")); + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response ConfigurationClient::CheckSnapshot( + std::string const& name, + CheckSnapshotOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("snapshots/"); + url.AppendPath(!name.empty() ? Core::Url::Encode(name) : "null"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + Core::Http::Request request(Core::Http::HttpMethod::Head, url); + + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("If-Match", options.IfMatch); + request.SetHeader("If-None-Match", options.IfNoneMatch); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + CheckSnapshotResult response{}; + response.SyncToken = rawResponse->GetHeaders().at("Sync-Token"); + response.ETag = rawResponse->GetHeaders().at("ETag"); + response.Link = rawResponse->GetHeaders().at("Link"); + + return Response(std::move(response), std::move(rawResponse)); +} + +GetLabelsPagedResponse ConfigurationClient::GetLabels( + std::string const& accept, + GetLabelsOptions const& options, + Core::Context const& context) +{ + auto url = m_url; + url.AppendPath("labels"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + url.AppendQueryParameter("name", Core::Url::Encode(options.Name)); + url.AppendQueryParameter("After", Core::Url::Encode(options.After)); + { + std::string valueStr; + for (size_t i = 0; i < options.Select.size(); ++i) + { + if (i != 0) + { + valueStr += ','; + } + + valueStr += Core::Url::Encode(options.Select[i].ToString()); + } + + url.AppendQueryParameter("$Select", valueStr); + } + + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + url.SetPort(m_url.GetPort()); + } + else if (!options.NextPageToken.empty()) + { + url.SetPath( + options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) : options.NextPageToken); + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", accept); + request.SetHeader("Sync-Token", options.SyncToken); + request.SetHeader("Accept-Datetime", options.AcceptDatetime); + request.SetHeader("x-ms-client-request-id", options.XMsClientRequestId.ToString()); + auto rawResponse = m_pipeline->Send(request, context); + auto const httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetLabelsPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_accept = accept; + response.m_options = options; + { + auto const& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + auto const jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("@nextLink") && !jsonRoot["@nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["@nextLink"].get(); + } + + if (jsonRoot.contains("items")) + { + response.Items = std::vector