From c9f07f138922febcfcff73624e1d118f9c4ba9f1 Mon Sep 17 00:00:00 2001 From: microzchang <110015819+microzchang@users.noreply.github.com> Date: Wed, 7 May 2025 16:45:25 +0800 Subject: [PATCH] Storage STG98 Features (#6501) * get set acl oauth (#6405) * Storage STG98/Added support for x-ms-file-request-intent for blob copy APIs (#6406) * Source File Copy Support * Storage STG98/NFS 2 (#6404) * feature * add test record * Update blob sas new string to sign (#6511) --- sdk/storage/assets.json | 2 +- .../inc/azure/storage/blobs/blob_options.hpp | 30 ++++ .../inc/azure/storage/blobs/rest_client.hpp | 23 ++- .../src/append_blob_client.cpp | 2 + .../azure-storage-blobs/src/blob_client.cpp | 1 + .../src/blob_sas_builder.cpp | 4 +- .../src/block_blob_client.cpp | 2 + .../src/page_blob_client.cpp | 2 + .../azure-storage-blobs/src/rest_client.cpp | 164 ++++++++++-------- .../azure-storage-blobs/swagger/README.md | 12 +- .../test/ut/CMakeLists.txt | 2 +- .../test/ut/append_blob_client_test.cpp | 36 ++++ .../test/ut/blob_container_client_test.cpp | 18 ++ .../test/ut/block_blob_client_test.cpp | 82 +++++++++ .../test/ut/page_blob_client_test.cpp | 38 ++++ .../ut/datalake_file_system_client_test.cpp | 15 ++ .../files/shares/share_file_client.hpp | 24 +++ .../storage/files/shares/share_options.hpp | 47 +++++ .../storage/files/shares/share_responses.hpp | 51 ++++++ .../src/share_file_client.cpp | 59 +++++++ .../test/ut/share_file_client_test.cpp | 56 +++++- .../test/ut/queue_client_test.cpp | 12 ++ 22 files changed, 599 insertions(+), 83 deletions(-) diff --git a/sdk/storage/assets.json b/sdk/storage/assets.json index cef6a7452..e7b3381e4 100644 --- a/sdk/storage/assets.json +++ b/sdk/storage/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "cpp", "TagPrefix": "cpp/storage", - "Tag": "cpp/storage_57a579efb6" + "Tag": "cpp/storage_7bea1dff90" } diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp index 31ef7c26d..44ffac00a 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/blob_options.hpp @@ -640,6 +640,12 @@ namespace Azure { namespace Storage { namespace Blobs { * source. */ std::string SourceAuthorization; + + /** + * Optional, only applicable (but required) when the source is Azure Storage Files and using + * token authentication. Used to indicate the intent of the request. + */ + Azure::Nullable FileRequestIntent; }; /** @@ -1017,6 +1023,12 @@ namespace Azure { namespace Storage { namespace Blobs { * source. */ std::string SourceAuthorization; + + /** + * Optional, only applicable (but required) when the source is Azure Storage Files and using + * token authentication. Used to indicate the intent of the request. + */ + Azure::Nullable FileRequestIntent; }; /** @@ -1073,6 +1085,12 @@ namespace Azure { namespace Storage { namespace Blobs { * source. */ std::string SourceAuthorization; + + /** + * Optional, only applicable (but required) when the source is Azure Storage Files and using + * token authentication. Used to indicate the intent of the request. + */ + Azure::Nullable FileRequestIntent; }; /** @@ -1366,6 +1384,12 @@ namespace Azure { namespace Storage { namespace Blobs { * source. */ std::string SourceAuthorization; + + /** + * Optional, only applicable (but required) when the source is Azure Storage Files and using + * token authentication. Used to indicate the intent of the request. + */ + Azure::Nullable FileRequestIntent; }; /** @@ -1477,6 +1501,12 @@ namespace Azure { namespace Storage { namespace Blobs { * source. */ std::string SourceAuthorization; + + /** + * Optional, only applicable (but required) when the source is Azure Storage Files and using + * token authentication. Used to indicate the intent of the request. + */ + Azure::Nullable FileRequestIntent; }; /** diff --git a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/rest_client.hpp b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/rest_client.hpp index 389f3d8fd..7ff932ae9 100644 --- a/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/rest_client.hpp +++ b/sdk/storage/azure-storage-blobs/inc/azure/storage/blobs/rest_client.hpp @@ -32,7 +32,7 @@ namespace Azure { namespace Storage { namespace Blobs { /** * The version used for the operations to Azure storage services. */ - constexpr static const char* ApiVersion = "2024-08-04"; + constexpr static const char* ApiVersion = "2025-07-05"; } // namespace _detail namespace Models { /** @@ -1756,7 +1756,7 @@ namespace Azure { namespace Storage { namespace Blobs { /** * The tier of page blob on a premium storage account or tier of block blob on blob storage * LRS accounts. For a list of allowed premium page blob tiers, see - * https://learn.microsoft.com/en-us/azure/virtual-machines/windows/premium-storage#features. + * https://docs.microsoft.com/en-us/azure/virtual-machines/windows/premium-storage#features. * For blob storage LRS accounts, valid values are Hot/Cool/Archive. */ Nullable AccessTier; @@ -2182,6 +2182,20 @@ namespace Azure { namespace Storage { namespace Blobs { /** Constant value of type BlobCopySourceTagsMode: Copy */ AZ_STORAGE_BLOBS_DLLEXPORT const static BlobCopySourceTagsMode Copy; }; + /** + * @brief Valid value is backup. + */ + class FileShareTokenIntent final + : public Core::_internal::ExtendableEnumeration { + public: + /** Constructs a new FileShareTokenIntent instance */ + FileShareTokenIntent() = default; + /** Constructs a new FileShareTokenIntent from a string. */ + explicit FileShareTokenIntent(std::string value) : ExtendableEnumeration(std::move(value)) {} + + /** Constant value of type FileShareTokenIntent: Backup */ + AZ_STORAGE_BLOBS_DLLEXPORT const static FileShareTokenIntent Backup; + }; /** * @brief Response type for #Azure::Storage::Blobs::BlobClient::CopyFromUri. */ @@ -3779,6 +3793,7 @@ namespace Azure { namespace Storage { namespace Blobs { Nullable CopySourceAuthorization; Nullable EncryptionScope; Nullable CopySourceTags; + Nullable FileRequestIntent; Nullable> SourceContentcrc64; }; static Response CopyFromUri( @@ -3971,6 +3986,7 @@ namespace Azure { namespace Storage { namespace Blobs { ETag SourceIfMatch; ETag SourceIfNoneMatch; Nullable CopySourceAuthorization; + Nullable FileRequestIntent; }; static Response UploadPagesFromUri( Core::Http::_internal::HttpPipeline& pipeline, @@ -4143,6 +4159,7 @@ namespace Azure { namespace Storage { namespace Blobs { ETag SourceIfMatch; ETag SourceIfNoneMatch; Nullable CopySourceAuthorization; + Nullable FileRequestIntent; }; static Response AppendBlockFromUri( Core::Http::_internal::HttpPipeline& pipeline, @@ -4230,6 +4247,7 @@ namespace Azure { namespace Storage { namespace Blobs { Nullable CopySourceBlobProperties; Nullable CopySourceAuthorization; Nullable CopySourceTags; + Nullable FileRequestIntent; Nullable> SourceContentcrc64; }; static Response UploadFromUri( @@ -4271,6 +4289,7 @@ namespace Azure { namespace Storage { namespace Blobs { ETag SourceIfMatch; ETag SourceIfNoneMatch; Nullable CopySourceAuthorization; + Nullable FileRequestIntent; }; static Response StageBlockFromUri( Core::Http::_internal::HttpPipeline& pipeline, diff --git a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp index f1ac91b66..33146b2e1 100644 --- a/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/append_blob_client.cpp @@ -220,6 +220,8 @@ namespace Azure { namespace Storage { namespace Blobs { { protocolLayerOptions.CopySourceAuthorization = options.SourceAuthorization; } + protocolLayerOptions.FileRequestIntent = options.FileRequestIntent; + return _detail::AppendBlobClient::AppendBlockFromUri( *m_pipeline, m_blobUrl, protocolLayerOptions, context); } diff --git a/sdk/storage/azure-storage-blobs/src/blob_client.cpp b/sdk/storage/azure-storage-blobs/src/blob_client.cpp index 555d47255..d1921a3f6 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_client.cpp @@ -714,6 +714,7 @@ namespace Azure { namespace Storage { namespace Blobs { { protocolLayerOptions.CopySourceAuthorization = options.SourceAuthorization; } + protocolLayerOptions.FileRequestIntent = options.FileRequestIntent; return _detail::BlobClient::CopyFromUri(*m_pipeline, m_blobUrl, protocolLayerOptions, context); } diff --git a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp index 666621943..1baa9f1ca 100644 --- a/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp +++ b/sdk/storage/azure-storage-blobs/src/blob_sas_builder.cpp @@ -261,7 +261,7 @@ namespace Azure { namespace Storage { namespace Sas { + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" + userDelegationKey.SignedTenantId + "\n" + signedStartsOnStr + "\n" + signedExpiresOnStr + "\n" + userDelegationKey.SignedService + "\n" + userDelegationKey.SignedVersion - + "\n\n\n\n" + (IPRange.HasValue() ? IPRange.Value() : "") + "\n" + protocol + "\n" + + "\n\n\n\n\n\n" + (IPRange.HasValue() ? IPRange.Value() : "") + "\n" + protocol + "\n" + SasVersion + "\n" + resource + "\n" + snapshotVersion + "\n" + EncryptionScope + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; @@ -397,7 +397,7 @@ namespace Azure { namespace Storage { namespace Sas { return Permissions + "\n" + startsOnStr + "\n" + expiresOnStr + "\n" + canonicalName + "\n" + userDelegationKey.SignedObjectId + "\n" + userDelegationKey.SignedTenantId + "\n" + signedStartsOnStr + "\n" + signedExpiresOnStr + "\n" + userDelegationKey.SignedService - + "\n" + userDelegationKey.SignedVersion + "\n\n\n\n" + + "\n" + userDelegationKey.SignedVersion + "\n\n\n\n\n\n" + (IPRange.HasValue() ? IPRange.Value() : "") + "\n" + protocol + "\n" + SasVersion + "\n" + resource + "\n" + snapshotVersion + "\n" + EncryptionScope + "\n" + CacheControl + "\n" + ContentDisposition + "\n" + ContentEncoding + "\n" + ContentLanguage + "\n" + ContentType; diff --git a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp index ccc2f69fa..f2ad3e3da 100644 --- a/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/block_blob_client.cpp @@ -383,6 +383,7 @@ namespace Azure { namespace Storage { namespace Blobs { { protocolLayerOptions.CopySourceAuthorization = options.SourceAuthorization; } + protocolLayerOptions.FileRequestIntent = options.FileRequestIntent; return _detail::BlockBlobClient::UploadFromUri( *m_pipeline, m_blobUrl, protocolLayerOptions, context); @@ -467,6 +468,7 @@ namespace Azure { namespace Storage { namespace Blobs { { protocolLayerOptions.CopySourceAuthorization = options.SourceAuthorization; } + protocolLayerOptions.FileRequestIntent = options.FileRequestIntent; return _detail::BlockBlobClient::StageBlockFromUri( *m_pipeline, m_blobUrl, protocolLayerOptions, context); diff --git a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp index 9a8759053..1b437e4e4 100644 --- a/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/page_blob_client.cpp @@ -237,6 +237,8 @@ namespace Azure { namespace Storage { namespace Blobs { { protocolLayerOptions.CopySourceAuthorization = options.SourceAuthorization; } + protocolLayerOptions.FileRequestIntent = options.FileRequestIntent; + return _detail::PageBlobClient::UploadPagesFromUri( *m_pipeline, m_blobUrl, protocolLayerOptions, context); } diff --git a/sdk/storage/azure-storage-blobs/src/rest_client.cpp b/sdk/storage/azure-storage-blobs/src/rest_client.cpp index f42493bd9..9d84e8e90 100644 --- a/sdk/storage/azure-storage-blobs/src/rest_client.cpp +++ b/sdk/storage/azure-storage-blobs/src/rest_client.cpp @@ -173,6 +173,7 @@ namespace Azure { namespace Storage { namespace Blobs { const ScheduleBlobExpiryOriginType ScheduleBlobExpiryOriginType::Absolute("Absolute"); const BlobCopySourceTagsMode BlobCopySourceTagsMode::Replace("REPLACE"); const BlobCopySourceTagsMode BlobCopySourceTagsMode::Copy("COPY"); + const FileShareTokenIntent FileShareTokenIntent::Backup("backup"); namespace _detail { const QueryRequestQueryType QueryRequestQueryType::SQL("SQL"); const QueryFormatType QueryFormatType::Delimited("delimited"); @@ -377,7 +378,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader("Content-Length", std::to_string(requestBody.Length())); request.GetUrl().AppendQueryParameter("restype", "service"); request.GetUrl().AppendQueryParameter("comp", "properties"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -397,7 +398,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "service"); request.GetUrl().AppendQueryParameter("comp", "properties"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -693,7 +694,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "service"); request.GetUrl().AppendQueryParameter("comp", "stats"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -793,7 +794,7 @@ namespace Azure { namespace Storage { namespace Blobs { _internal::UrlEncodeQueryParameter( ListBlobContainersIncludeFlagsToString(options.Include.Value()))); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1078,7 +1079,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader("Content-Length", std::to_string(requestBody.Length())); request.GetUrl().AppendQueryParameter("restype", "service"); request.GetUrl().AppendQueryParameter("comp", "userdelegationkey"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1193,7 +1194,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "account"); request.GetUrl().AppendQueryParameter("comp", "properties"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -1223,7 +1224,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("Content-Type", options.MultipartContentType); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -1244,7 +1245,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("comp", "blobs"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.Where.HasValue() && !options.Where.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -1400,7 +1401,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-blob-public-access", options.Access.ToString()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.DefaultEncryptionScope.HasValue() && !options.DefaultEncryptionScope.Value().empty()) { @@ -1437,7 +1438,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1515,7 +1516,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -1549,7 +1550,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Modified-Since", options.IfModifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1576,7 +1577,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1745,7 +1746,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -1768,7 +1769,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("restype", "container"); request.GetUrl().AppendQueryParameter("comp", "undelete"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.DeletedContainerName.HasValue() && !options.DeletedContainerName.Value().empty()) { request.SetHeader("x-ms-deleted-container-name", options.DeletedContainerName.Value()); @@ -1798,7 +1799,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("restype", "container"); request.GetUrl().AppendQueryParameter("comp", "rename"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (!options.SourceContainerName.empty()) { request.SetHeader("x-ms-source-container-name", options.SourceContainerName); @@ -1832,7 +1833,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("Content-Type", options.MultipartContentType); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -1854,7 +1855,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "container"); request.GetUrl().AppendQueryParameter("comp", "blobs"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.Where.HasValue() && !options.Where.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -2024,7 +2025,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -2065,7 +2066,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -2105,7 +2106,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -2146,7 +2147,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -2191,7 +2192,7 @@ namespace Azure { namespace Storage { namespace Blobs { "If-Unmodified-Since", options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123)); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -2238,7 +2239,7 @@ namespace Azure { namespace Storage { namespace Blobs { _internal::UrlEncodeQueryParameter( ListBlobsIncludeFlagsToString(options.Include.Value()))); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -2917,7 +2918,7 @@ namespace Azure { namespace Storage { namespace Blobs { _internal::UrlEncodeQueryParameter( ListBlobsIncludeFlagsToString(options.Include.Value()))); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.ShowOnly.HasValue() && !options.ShowOnly.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -3606,7 +3607,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "account"); request.GetUrl().AppendQueryParameter("comp", "properties"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -3697,7 +3698,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.UserPrincipalName.HasValue()) { request.SetHeader("x-ms-upn", options.UserPrincipalName.Value() ? "true" : "false"); @@ -3977,7 +3978,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.UserPrincipalName.HasValue()) { request.SetHeader("x-ms-upn", options.UserPrincipalName.Value() ? "true" : "false"); @@ -4243,7 +4244,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -4261,7 +4262,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("comp", "undelete"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -4280,7 +4281,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("comp", "expiry"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (!options.ExpiryOptions.ToString().empty()) { request.SetHeader("x-ms-expiry-option", options.ExpiryOptions.ToString()); @@ -4368,7 +4369,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-blob-content-disposition", options.BlobContentDisposition); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -4401,7 +4402,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("comp", "immutabilityPolicies"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.IfUnmodifiedSince.HasValue()) { request.SetHeader( @@ -4444,7 +4445,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Delete, url); request.GetUrl().AppendQueryParameter("comp", "immutabilityPolicies"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -4464,7 +4465,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("comp", "legalhold"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); request.SetHeader("x-ms-legal-hold", options.LegalHold ? "true" : "false"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -4536,7 +4537,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -4611,7 +4612,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -4669,7 +4670,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -4726,7 +4727,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -4788,7 +4789,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -4846,7 +4847,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -4926,7 +4927,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -5033,7 +5034,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.BlobTagsString.HasValue() && !options.BlobTagsString.Value().empty()) { request.SetHeader("x-ms-tags", options.BlobTagsString.Value()); @@ -5152,7 +5153,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.SourceContentMD5.HasValue() && !Core::Convert::Base64Encode(options.SourceContentMD5.Value()).empty()) { @@ -5195,6 +5196,11 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-copy-source-tag-option", options.CopySourceTags.Value().ToString()); } + if (options.FileRequestIntent.HasValue() + && !options.FileRequestIntent.Value().ToString().empty()) + { + request.SetHeader("x-ms-file-request-intent", options.FileRequestIntent.Value().ToString()); + } if (options.SourceContentcrc64.HasValue() && !Core::Convert::Base64Encode(options.SourceContentcrc64.Value()).empty()) { @@ -5262,7 +5268,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::NoContent) @@ -5300,7 +5306,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-rehydrate-priority", options.RehydratePriority.Value().ToString()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.LeaseId.HasValue() && !options.LeaseId.Value().empty()) { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); @@ -5329,7 +5335,7 @@ namespace Azure { namespace Storage { namespace Blobs { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("restype", "account"); request.GetUrl().AppendQueryParameter("comp", "properties"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); (void)options; auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); @@ -5627,7 +5633,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.EncryptionScope.HasValue() && !options.EncryptionScope.Value().empty()) { request.SetHeader("x-ms-encryption-scope", options.EncryptionScope.Value()); @@ -5676,7 +5682,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url); request.GetUrl().AppendQueryParameter("comp", "tags"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.Snapshot.HasValue() && !options.Snapshot.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -5803,7 +5809,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader("Content-Type", "application/xml; charset=UTF-8"); request.SetHeader("Content-Length", std::to_string(requestBody.Length())); request.GetUrl().AppendQueryParameter("comp", "tags"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.VersionId.HasValue() && !options.VersionId.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -5934,7 +5940,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader( "x-ms-blob-sequence-number", std::to_string(options.BlobSequenceNumber.Value())); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.BlobTagsString.HasValue() && !options.BlobTagsString.Value().empty()) { request.SetHeader("x-ms-tags", options.BlobTagsString.Value()); @@ -6080,7 +6086,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -6206,7 +6212,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -6349,13 +6355,18 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch.ToString()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.CopySourceAuthorization.HasValue() && !options.CopySourceAuthorization.Value().empty()) { request.SetHeader( "x-ms-copy-source-authorization", options.CopySourceAuthorization.Value()); } + if (options.FileRequestIntent.HasValue() + && !options.FileRequestIntent.Value().ToString().empty()) + { + request.SetHeader("x-ms-file-request-intent", options.FileRequestIntent.Value().ToString()); + } auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -6450,7 +6461,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.Marker.HasValue() && !options.Marker.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -6628,7 +6639,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.Marker.HasValue() && !options.Marker.Value().empty()) { request.GetUrl().AppendQueryParameter( @@ -6808,7 +6819,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } request.SetHeader("x-ms-blob-content-length", std::to_string(options.BlobContentLength)); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -6874,7 +6885,7 @@ namespace Azure { namespace Storage { namespace Blobs { request.SetHeader( "x-ms-blob-sequence-number", std::to_string(options.BlobSequenceNumber.Value())); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) @@ -6932,7 +6943,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-copy-source", options.CopySource); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Accepted) @@ -7043,7 +7054,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.BlobTagsString.HasValue() && !options.BlobTagsString.Value().empty()) { request.SetHeader("x-ms-tags", options.BlobTagsString.Value()); @@ -7171,7 +7182,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -7325,13 +7336,18 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch.ToString()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.CopySourceAuthorization.HasValue() && !options.CopySourceAuthorization.Value().empty()) { request.SetHeader( "x-ms-copy-source-authorization", options.CopySourceAuthorization.Value()); } + if (options.FileRequestIntent.HasValue() + && !options.FileRequestIntent.Value().ToString().empty()) + { + request.SetHeader("x-ms-file-request-intent", options.FileRequestIntent.Value().ToString()); + } auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -7381,7 +7397,7 @@ namespace Azure { namespace Storage { namespace Blobs { { auto request = Core::Http::Request(Core::Http::HttpMethod::Put, url); request.GetUrl().AppendQueryParameter("comp", "seal"); - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.LeaseId.HasValue() && !options.LeaseId.Value().empty()) { request.SetHeader("x-ms-lease-id", options.LeaseId.Value()); @@ -7520,7 +7536,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.BlobTagsString.HasValue() && !options.BlobTagsString.Value().empty()) { request.SetHeader("x-ms-tags", options.BlobTagsString.Value()); @@ -7703,7 +7719,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-source-if-tags", options.SourceIfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.SourceContentMD5.HasValue() && !Core::Convert::Base64Encode(options.SourceContentMD5.Value()).empty()) { @@ -7735,6 +7751,11 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-copy-source-tag-option", options.CopySourceTags.Value().ToString()); } + if (options.FileRequestIntent.HasValue() + && !options.FileRequestIntent.Value().ToString().empty()) + { + request.SetHeader("x-ms-file-request-intent", options.FileRequestIntent.Value().ToString()); + } if (options.SourceContentcrc64.HasValue() && !Core::Convert::Base64Encode(options.SourceContentcrc64.Value()).empty()) { @@ -7835,7 +7856,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-encryption-scope", options.EncryptionScope.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -7949,13 +7970,18 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-source-if-none-match", options.SourceIfNoneMatch.ToString()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.CopySourceAuthorization.HasValue() && !options.CopySourceAuthorization.Value().empty()) { request.SetHeader( "x-ms-copy-source-authorization", options.CopySourceAuthorization.Value()); } + if (options.FileRequestIntent.HasValue() + && !options.FileRequestIntent.Value().ToString().empty()) + { + request.SetHeader("x-ms-file-request-intent", options.FileRequestIntent.Value().ToString()); + } auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Created) @@ -8116,7 +8142,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); if (options.BlobTagsString.HasValue() && !options.BlobTagsString.Value().empty()) { request.SetHeader("x-ms-tags", options.BlobTagsString.Value()); @@ -8205,7 +8231,7 @@ namespace Azure { namespace Storage { namespace Blobs { { request.SetHeader("x-ms-if-tags", options.IfTags.Value()); } - request.SetHeader("x-ms-version", "2024-08-04"); + request.SetHeader("x-ms-version", "2025-07-05"); auto pRawResponse = pipeline.Send(request, context); auto httpStatusCode = pRawResponse->GetStatusCode(); if (httpStatusCode != Core::Http::HttpStatusCode::Ok) diff --git a/sdk/storage/azure-storage-blobs/swagger/README.md b/sdk/storage/azure-storage-blobs/swagger/README.md index c3bbde379..bd78d7fd5 100644 --- a/sdk/storage/azure-storage-blobs/swagger/README.md +++ b/sdk/storage/azure-storage-blobs/swagger/README.md @@ -9,7 +9,7 @@ package-name: azure-storage-blobs namespace: Azure::Storage::Blobs output-folder: generated clear-output-folder: true -input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Microsoft.BlobStorage/stable/2024-08-04/blob.json +input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Microsoft.BlobStorage/stable/2025-07-05/blob.json ``` ## ModelFour Options @@ -52,12 +52,13 @@ directive: - from: swagger-document where: $["x-ms-paths"].*.*.parameters transform: > - $ = $.filter(p => !(p["$ref"] && (p["$ref"].endsWith("#/parameters/Timeout") || p["$ref"].endsWith("#/parameters/ClientRequestId")))); + $ = $.filter(p => !(p["$ref"] && (p["$ref"].endsWith("#/parameters/Timeout") || p["$ref"].endsWith("#/parameters/ClientRequestId") + || p["$ref"].endsWith("#/parameters/StructuredBodyGet") || p["$ref"].endsWith("#/parameters/StructuredBodyPut") || p["$ref"].endsWith("#/parameters/StructuredContentLength")))); - from: swagger-document where: $["x-ms-paths"].*.*.responses.*.headers transform: > for (const h in $) { - if (["x-ms-client-request-id", "x-ms-request-id", "x-ms-version", "Date"].includes(h)) { + if (["x-ms-client-request-id", "x-ms-request-id", "x-ms-version", "Date", "x-ms-structured-body", "x-ms-structured-content-length"].includes(h)) { delete $[h]; } } @@ -100,12 +101,12 @@ directive: "name": "ApiVersion", "modelAsString": false }, - "enum": ["2024-08-04"] + "enum": ["2025-07-05"] }; - from: swagger-document where: $.parameters transform: > - $.ApiVersionParameter.enum[0] = "2024-08-04"; + $.ApiVersionParameter.enum[0] = "2025-07-05"; ``` ### Rename Operations @@ -293,6 +294,7 @@ directive: $.ImmutabilityPolicyMode.enum = $.ImmutabilityPolicyMode.enum.map(e => e.toLowerCase()); $.CopySourceTags["x-ms-enum"]["name"] = "BlobCopySourceTagsMode"; delete $.FilterBlobsInclude; + $.FileRequestIntent["x-ms-enum"]["values"] = [{"value": "__placeHolder", "name": "__placeHolder"}, {"value": "backup", "name": "Backup"}]; - from: swagger-document where: $.definitions transform: > diff --git a/sdk/storage/azure-storage-blobs/test/ut/CMakeLists.txt b/sdk/storage/azure-storage-blobs/test/ut/CMakeLists.txt index 56f4844d9..60b496cac 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/CMakeLists.txt +++ b/sdk/storage/azure-storage-blobs/test/ut/CMakeLists.txt @@ -49,7 +49,7 @@ create_map_file(azure-storage-blobs-test azure-storage-blobs-test.map) # Include shared test headers target_include_directories(azure-storage-blobs-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../azure-storage-common) -target_link_libraries(azure-storage-blobs-test PRIVATE azure-identity azure-storage-blobs azure-core-test-fw gtest gtest_main gmock) +target_link_libraries(azure-storage-blobs-test PRIVATE azure-identity azure-storage-blobs azure-storage-files-shares azure-core-test-fw gtest gtest_main gmock) # gtest_discover_tests will scan the test from azure-storage-blobs-test and call add_test # for each test to ctest. This enables `ctest -r` to run specific tests directly. diff --git a/sdk/storage/azure-storage-blobs/test/ut/append_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/append_blob_client_test.cpp index c72ff20fa..bfcb02d12 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/append_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/append_blob_client_test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Azure { namespace Storage { namespace Blobs { namespace Models { @@ -467,4 +468,39 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ(blobContent.size(), properties.BlobSize); } + TEST_F(AppendBlobClientTest, OAuthAppendBlockFromUri_SourceFileShare_PLAYBACKONLY_) + { + auto shareClientOptions = InitStorageClientOptions(); + shareClientOptions.ShareTokenIntent = Files::Shares::Models::ShareTokenIntent::Backup; + auto oauthCredential = GetTestCredential(); + auto shareServiceClient = Files::Shares::ShareServiceClient::CreateFromConnectionString( + StandardStorageConnectionString(), shareClientOptions); + shareServiceClient = Files::Shares::ShareServiceClient( + shareServiceClient.GetUrl(), oauthCredential, shareClientOptions); + auto shareClient = shareServiceClient.GetShareClient(LowercaseRandomString()); + shareClient.Create(); + + size_t fileSize = 1 * 1024; + std::string fileName = RandomString() + "file"; + std::vector fileContent = RandomBuffer(fileSize); + auto memBodyStream = Core::IO::MemoryBodyStream(fileContent); + auto sourceFileClient = shareClient.GetRootDirectoryClient().GetFileClient(fileName); + sourceFileClient.Create(fileSize); + EXPECT_NO_THROW(sourceFileClient.UploadRange(0, memBodyStream)); + + Azure::Core::Credentials::TokenRequestContext requestContext; + requestContext.Scopes = {Storage::_internal::StorageScope}; + + auto oauthToken = oauthCredential->GetToken(requestContext, Azure::Core::Context()); + + auto destBlobClient = GetAppendBlobClientForTest(RandomString()); + EXPECT_NO_THROW(destBlobClient.Create()); + Storage::Blobs::AppendBlockFromUriOptions options; + options.SourceAuthorization = "Bearer " + oauthToken.Token; + options.FileRequestIntent = Blobs::Models::FileShareTokenIntent::Backup; + EXPECT_NO_THROW(destBlobClient.AppendBlockFromUri(sourceFileClient.GetUrl(), options)); + + EXPECT_NO_THROW(shareClient.DeleteIfExists()); + } + }}} // namespace Azure::Storage::Test diff --git a/sdk/storage/azure-storage-blobs/test/ut/blob_container_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/blob_container_client_test.cpp index f22c586a9..6ff874c7d 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/blob_container_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/blob_container_client_test.cpp @@ -508,6 +508,24 @@ namespace Azure { namespace Storage { namespace Test { containerClient.DeleteIfExists(); } + TEST_F(BlobContainerClientTest, AclAndAccountInfoOAuth_PLAYBACKONLY_) + { + auto credential = GetTestCredential(); + auto clientOptions = InitStorageClientOptions(); + auto containerClient + = Blobs::BlobContainerClient(m_blobContainerClient->GetUrl(), credential, clientOptions); + + Blobs::SetBlobContainerAccessPolicyOptions options; + auto ret = containerClient.SetAccessPolicy(options); + EXPECT_TRUE(ret.Value.ETag.HasValue()); + EXPECT_TRUE(IsValidTime(ret.Value.LastModified)); + + EXPECT_NO_THROW(containerClient.GetAccessPolicy()); + + auto ret3 = containerClient.GetAccountInfo(); + EXPECT_FALSE(ret3.Value.IsHierarchicalNamespaceEnabled); + } + TEST_F(BlobContainerClientTest, Lease) { auto containerClient = *m_blobContainerClient; diff --git a/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp index 03c76ae6d..4de5e08e4 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/block_blob_client_test.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -491,6 +492,87 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_FALSE(blobItem.Details.IncrementalCopyDestinationSnapshot.HasValue()); } + TEST_F(BlockBlobClientTest, OAuthCopyFromUri_SourceFileShare_PLAYBACKONLY_) + { + auto shareClientOptions = InitStorageClientOptions(); + shareClientOptions.ShareTokenIntent = Files::Shares::Models::ShareTokenIntent::Backup; + auto oauthCredential = GetTestCredential(); + auto shareServiceClient = Files::Shares::ShareServiceClient::CreateFromConnectionString( + StandardStorageConnectionString(), shareClientOptions); + shareServiceClient = Files::Shares::ShareServiceClient( + shareServiceClient.GetUrl(), oauthCredential, shareClientOptions); + auto shareClient = shareServiceClient.GetShareClient(LowercaseRandomString()); + shareClient.Create(); + + size_t fileSize = 1 * 1024; + std::string fileName = RandomString() + "file"; + std::vector fileContent = RandomBuffer(fileSize); + auto memBodyStream = Core::IO::MemoryBodyStream(fileContent); + auto sourceFileClient = shareClient.GetRootDirectoryClient().GetFileClient(fileName); + sourceFileClient.Create(fileSize); + EXPECT_NO_THROW(sourceFileClient.UploadRange(0, memBodyStream)); + + Azure::Core::Credentials::TokenRequestContext requestContext; + requestContext.Scopes = {Storage::_internal::StorageScope}; + auto oauthToken = oauthCredential->GetToken(requestContext, Azure::Core::Context()); + + const std::string blobName = "dest" + RandomString(); + auto destBlobClient = m_blobContainerClient->GetBlockBlobClient(blobName); + + // Copy From Uri + Storage::Blobs::CopyBlobFromUriOptions copyOptions; + copyOptions.SourceAuthorization = "Bearer " + oauthToken.Token; + copyOptions.FileRequestIntent = Azure::Storage::Blobs::Models::FileShareTokenIntent::Backup; + auto res = destBlobClient.CopyFromUri(sourceFileClient.GetUrl(), copyOptions); + EXPECT_EQ(res.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::Accepted); + EXPECT_TRUE(res.Value.ETag.HasValue()); + EXPECT_TRUE(IsValidTime(res.Value.LastModified)); + EXPECT_FALSE(res.Value.CopyId.empty()); + EXPECT_EQ(res.Value.CopyStatus, Azure::Storage::Blobs::Models::CopyStatus::Success); + + auto downloadResult = destBlobClient.Download(); + EXPECT_FALSE(downloadResult.Value.Details.CopyId.Value().empty()); + EXPECT_FALSE(downloadResult.Value.Details.CopySource.Value().empty()); + EXPECT_TRUE( + downloadResult.Value.Details.CopyStatus.Value() + == Azure::Storage::Blobs::Models::CopyStatus::Success); + EXPECT_FALSE(downloadResult.Value.Details.CopyProgress.Value().empty()); + EXPECT_TRUE(IsValidTime(downloadResult.Value.Details.CopyCompletedOn.Value())); + + auto blobItem = GetBlobItem(blobName, Blobs::Models::ListBlobsIncludeFlags::Copy); + EXPECT_FALSE(blobItem.Details.CopyId.Value().empty()); + EXPECT_FALSE(blobItem.Details.CopySource.Value().empty()); + EXPECT_TRUE( + blobItem.Details.CopyStatus.Value() == Azure::Storage::Blobs::Models::CopyStatus::Success); + EXPECT_FALSE(blobItem.Details.CopyProgress.Value().empty()); + EXPECT_TRUE(IsValidTime(blobItem.Details.CopyCompletedOn.Value())); + ASSERT_TRUE(blobItem.Details.IsIncrementalCopy.HasValue()); + EXPECT_FALSE(blobItem.Details.IsIncrementalCopy.Value()); + EXPECT_FALSE(blobItem.Details.IncrementalCopyDestinationSnapshot.HasValue()); + + // Upload From Uri + Storage::Blobs::UploadBlockBlobFromUriOptions uploadOptions; + uploadOptions.SourceAuthorization = "Bearer " + oauthToken.Token; + uploadOptions.FileRequestIntent = Azure::Storage::Blobs::Models::FileShareTokenIntent::Backup; + EXPECT_NO_THROW(destBlobClient.UploadFromUri(sourceFileClient.GetUrl(), uploadOptions)); + + // Stage Block From Uri + const std::string blockId1 = Base64EncodeText("0"); + const std::string blobName2 = "dest2" + RandomString(); + auto destBlobClient2 = m_blobContainerClient->GetBlockBlobClient(blobName2); + + Storage::Blobs::StageBlockFromUriOptions stageBlockOptions; + stageBlockOptions.SourceAuthorization = "Bearer " + oauthToken.Token; + stageBlockOptions.FileRequestIntent + = Azure::Storage::Blobs::Models::FileShareTokenIntent::Backup; + EXPECT_NO_THROW( + destBlobClient2.StageBlockFromUri(blockId1, sourceFileClient.GetUrl(), stageBlockOptions)); + + EXPECT_NO_THROW(destBlobClient2.CommitBlockList({blockId1})); + + EXPECT_NO_THROW(shareClient.DeleteIfExists()); + } + TEST_F(BlockBlobClientTest, SyncCopyFromUriEncryptionScope) { Blobs::BlobClientOptions clientOptions; diff --git a/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp b/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp index 44bb71f86..5c2435d91 100644 --- a/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp +++ b/sdk/storage/azure-storage-blobs/test/ut/page_blob_client_test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -301,6 +302,43 @@ namespace Azure { namespace Storage { namespace Test { pageBlobClient.Download().Value.BodyStream->ReadToEnd()); } + TEST_F(PageBlobClientTest, OAuthUploadFromUri_SourceFileShare_PLAYBACKONLY_) + { + auto shareClientOptions = InitStorageClientOptions(); + shareClientOptions.ShareTokenIntent = Files::Shares::Models::ShareTokenIntent::Backup; + auto oauthCredential = GetTestCredential(); + auto shareServiceClient = Files::Shares::ShareServiceClient::CreateFromConnectionString( + StandardStorageConnectionString(), shareClientOptions); + shareServiceClient = Files::Shares::ShareServiceClient( + shareServiceClient.GetUrl(), oauthCredential, shareClientOptions); + auto shareClient = shareServiceClient.GetShareClient(LowercaseRandomString()); + shareClient.Create(); + + size_t fileSize = 1 * 1024; + std::string fileName = RandomString() + "file"; + std::vector fileContent = RandomBuffer(fileSize); + auto memBodyStream = Core::IO::MemoryBodyStream(fileContent); + auto sourceFileClient = shareClient.GetRootDirectoryClient().GetFileClient(fileName); + sourceFileClient.Create(fileSize); + EXPECT_NO_THROW(sourceFileClient.UploadRange(0, memBodyStream)); + + auto destBlobClient = GetPageBlobClientTestForTest(RandomString()); + destBlobClient.Create(fileSize); + + Azure::Core::Credentials::TokenRequestContext requestContext; + requestContext.Scopes = {Storage::_internal::StorageScope}; + auto oauthToken = oauthCredential->GetToken(requestContext, Azure::Core::Context()); + + Storage::Blobs::UploadPagesFromUriOptions options; + options.SourceAuthorization = "Bearer " + oauthToken.Token; + options.FileRequestIntent = Blobs::Models::FileShareTokenIntent::Backup; + EXPECT_NO_THROW(destBlobClient.UploadPagesFromUri( + 0, sourceFileClient.GetUrl(), {0, static_cast(fileSize)}, options)); + EXPECT_EQ(destBlobClient.Download().Value.BodyStream->ReadToEnd(), fileContent); + + EXPECT_NO_THROW(shareClient.DeleteIfExists()); + } + TEST_F(PageBlobClientTest, StartCopyIncremental_LIVEONLY_) { auto pageBlobClient = *m_pageBlobClient; diff --git a/sdk/storage/azure-storage-files-datalake/test/ut/datalake_file_system_client_test.cpp b/sdk/storage/azure-storage-files-datalake/test/ut/datalake_file_system_client_test.cpp index f85865a14..6a62ccc10 100644 --- a/sdk/storage/azure-storage-files-datalake/test/ut/datalake_file_system_client_test.cpp +++ b/sdk/storage/azure-storage-files-datalake/test/ut/datalake_file_system_client_test.cpp @@ -714,6 +714,21 @@ namespace Azure { namespace Storage { namespace Test { } } + TEST_F(DataLakeFileSystemClientTest, AclOAuth_PLAYBACKONLY_) + { + auto credential = GetTestCredential(); + auto clientOptions = InitStorageClientOptions(); + auto fileSystemClient = Files::DataLake::DataLakeFileSystemClient( + m_fileSystemClient->GetUrl(), credential, clientOptions); + + Files::DataLake::SetFileSystemAccessPolicyOptions options; + auto ret = fileSystemClient.SetAccessPolicy(options); + EXPECT_TRUE(ret.Value.ETag.HasValue()); + EXPECT_TRUE(IsValidTime(ret.Value.LastModified)); + + EXPECT_NO_THROW(fileSystemClient.GetAccessPolicy()); + } + TEST_F(DataLakeFileSystemClientTest, RenameFile) { const std::string oldFilename = RandomString() + "1"; diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp index 08ce9a989..94026ef92 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_file_client.hpp @@ -379,6 +379,30 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { const UploadFileRangeFromUriOptions& options = UploadFileRangeFromUriOptions(), const Azure::Core::Context& context = Azure::Core::Context()) const; + /** + * @brief NFS only. Creates a symbolic link to the file specified by path. + * @param linkText The absolution or relative path to the file to be linked to. + * @param options Optional parameters to create this file's symbolic link. + * @param context Context for cancelling long running operations. + * @return Azure::Response containing the returned + * information. + */ + Azure::Response CreateSymbolicLink( + const std::string& linkText, + const CreateSymbolicLinkOptions& options = CreateSymbolicLinkOptions(), + const Azure::Core::Context& context = Azure::Core::Context()) const; + + /** + * @brief NFS only. Reads the value of the symbolic link. + * @param options Optional parameters to get this file's symbolic link. + * @param context Context for cancelling long running operations. + * @return Azure::Response containing the returned + * information. + */ + Azure::Response GetSymbolicLink( + const GetSymbolicLinkOptions& options = GetSymbolicLinkOptions(), + const Azure::Core::Context& context = Azure::Core::Context()) const; + /** * @brief NFS only. Creates a hard link to the file specified by path. * @param targetFile Path of the file to create the hard link to, not including the share. diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_options.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_options.hpp index 40b134de4..874da3538 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_options.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_options.hpp @@ -1387,6 +1387,53 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { { }; + /** + * @brief Optional parameters for + * #Azure::Storage::Files::Shares::ShareFileClient::CreateSymbolicLink. + */ + struct CreateSymbolicLinkOptions final + { + /** + * A name-value pair to associate with a file storage object. + */ + Storage::Metadata Metadata; + + /** + * Creation time for the file or directory. + */ + Nullable CreatedOn; + + /** + * Last write time for the file or directory. + */ + Nullable LastWrittenOn; + + /** + * Specify the access condition for the path. + */ + LeaseAccessConditions AccessConditions; + + /** + * NFS only. The owner user identifier (UID) to be set on the symbolic link. The default value + * is 0 (root). + */ + Nullable Owner; + + /** + * NFS only. The owner group identifier (GID) to be set on the symbolic link. The default value + * is 0 (root group). + */ + Nullable Group; + }; + + /** + * @brief Optional parameters for + * #Azure::Storage::Files::Shares::ShareFileClient::GetSymbolicLink. + */ + struct GetSymbolicLinkOptions final + { + }; + /** * @brief Optional parameters for * #Azure::Storage::Files::Shares::ShareFileClient::CreateHardLink. diff --git a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp index 79bcfde4d..9535f9e16 100644 --- a/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp +++ b/sdk/storage/azure-storage-files-shares/inc/azure/storage/files/shares/share_responses.hpp @@ -591,6 +591,57 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { FilePosixProperties PosixProperties; }; + /** + * @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::CreateSymbolicLink. + */ + struct CreateFileSymbolicLinkResult final + { + /** + * The ETag contains a value which represents the version of the file, in quotes. + */ + Azure::ETag ETag; + + /** + * Returns the date and time the share was last modified. Any operation that modifies the + * directory or its properties updates the last modified time. Operations on files do not + * affect the last modified time of the directory. + */ + DateTime LastModified; + + /** + * The SMB related properties for the file. + */ + FileSmbProperties SmbProperties; + + /** + * The NFS related properties for the file. + */ + FilePosixProperties PosixProperties; + }; + + /** + * @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::GetSymbolicLink. + */ + struct GetFileSymbolicLinkResult final + { + /** + * The ETag contains a value which represents the version of the file, in quotes. + */ + Azure::ETag ETag; + /** + * Returns the date and time the share was last modified. Any operation that modifies the + * directory or its properties updates the last modified time. Operations on files do not + * affect the last modified time of the directory. + */ + DateTime LastModified; + /** + * The path to the original file, the symbolic link is pointing to. The path is of type + * string which is not resolved and is stored as is. The path can be absolute path or the + * relative path depending on the content stored in the symbolic link file. + */ + std::string LinkText; + }; + /** * @brief Response type for #Azure::Storage::Files::Shares::ShareFileClient::CreateHardLink. */ diff --git a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp index b1aa1e314..b3865732a 100644 --- a/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp +++ b/sdk/storage/azure-storage-files-shares/src/share_file_client.cpp @@ -1434,6 +1434,65 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { *m_pipeline, m_shareFileUrl, protocolLayerOptions, context); } + Azure::Response ShareFileClient::CreateSymbolicLink( + const std::string& linkText, + const CreateSymbolicLinkOptions& options, + const Azure::Core::Context& context) const + { + _detail::FileClient::CreateFileSymbolicLinkOptions protocolLayerOptions; + protocolLayerOptions.LinkText = linkText; + if (options.CreatedOn.HasValue()) + { + protocolLayerOptions.FileCreationTime = options.CreatedOn.Value().ToString( + Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits); + } + + if (options.LastWrittenOn.HasValue()) + { + protocolLayerOptions.FileLastWriteTime = options.LastWrittenOn.Value().ToString( + Azure::DateTime::DateFormat::Rfc3339, DateTime::TimeFractionFormat::AllDigits); + } + + protocolLayerOptions.FileRequestIntent = m_shareTokenIntent; + protocolLayerOptions.Owner = options.Owner; + protocolLayerOptions.Group = options.Group; + protocolLayerOptions.Metadata + = std::map(options.Metadata.begin(), options.Metadata.end()); + protocolLayerOptions.LeaseId = options.AccessConditions.LeaseId; + + auto response = _detail::FileClient::CreateSymbolicLink( + *m_pipeline, m_shareFileUrl, protocolLayerOptions, context); + + Models::CreateFileSymbolicLinkResult ret; + ret.ETag = std::move(response.Value.ETag); + ret.SmbProperties = std::move(response.Value.SmbProperties); + ret.LastModified = std::move(response.Value.LastModified); + ret.PosixProperties.FileMode = Models::NfsFileMode::ParseOctalFileMode(response.Value.FileMode); + ret.PosixProperties.Owner = std::move(response.Value.Owner); + ret.PosixProperties.Group = std::move(response.Value.Group); + ret.PosixProperties.NfsFileType = std::move(response.Value.NfsFileType); + return Azure::Response( + std::move(ret), std::move(response.RawResponse)); + } + + Azure::Response ShareFileClient::GetSymbolicLink( + const GetSymbolicLinkOptions& options, + const Azure::Core::Context& context) const + { + (void)options; + _detail::FileClient::GetFileSymbolicLinkOptions protocolLayerOptions; + protocolLayerOptions.FileRequestIntent = m_shareTokenIntent; + auto response = _detail::FileClient::GetSymbolicLink( + *m_pipeline, m_shareFileUrl, protocolLayerOptions, context); + + Models::GetFileSymbolicLinkResult ret; + ret.ETag = std::move(response.Value.ETag); + ret.LastModified = std::move(response.Value.LastModified); + ret.LinkText = std::move(response.Value.LinkText); + return Azure::Response( + std::move(ret), std::move(response.RawResponse)); + } + Azure::Response ShareFileClient::CreateHardLink( const std::string& targetFile, const CreateHardLinkOptions& options, diff --git a/sdk/storage/azure-storage-files-shares/test/ut/share_file_client_test.cpp b/sdk/storage/azure-storage-files-shares/test/ut/share_file_client_test.cpp index 25df61deb..78bacb26c 100644 --- a/sdk/storage/azure-storage-files-shares/test/ut/share_file_client_test.cpp +++ b/sdk/storage/azure-storage-files-shares/test/ut/share_file_client_test.cpp @@ -2211,7 +2211,7 @@ namespace Azure { namespace Storage { namespace Test { } } - TEST_F(FileShareFileClientTest, PremiumNfsProperties_PLAYBACKONLY_) + TEST_F(FileShareFileClientTest, PremiumPosixProperties_PLAYBACKONLY_) { auto shareServiceClient = *m_premiumShareServiceClient; @@ -2332,6 +2332,56 @@ namespace Azure { namespace Storage { namespace Test { setOptions.PosixProperties.Owner.Value()); EXPECT_TRUE(downloadToResult.Details.PosixProperties.LinkCount.HasValue()); + // Create SymbolicLink + std::string sourceUrl = fileClient.GetUrl(); + auto symbolicLinkClient + = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString()); + Files::Shares::CreateSymbolicLinkOptions createSymbolicLinkOptions; + createSymbolicLinkOptions.CreatedOn = otherProperties.SmbProperties.CreatedOn; + createSymbolicLinkOptions.LastWrittenOn = otherProperties.SmbProperties.LastWrittenOn; + + createSymbolicLinkOptions.Metadata = RandomMetadata(); + createSymbolicLinkOptions.Group = "123"; + createSymbolicLinkOptions.Owner = "456"; + Files::Shares::Models::CreateFileSymbolicLinkResult createSymbolicLinkResult; + EXPECT_NO_THROW( + createSymbolicLinkResult + = symbolicLinkClient.CreateSymbolicLink(sourceUrl, createSymbolicLinkOptions).Value); + EXPECT_TRUE(createSymbolicLinkResult.PosixProperties.FileMode.HasValue()); + EXPECT_EQ( + createSymbolicLinkResult.PosixProperties.FileMode.Value().ToOctalFileMode(), octalMode); + EXPECT_TRUE(createSymbolicLinkResult.PosixProperties.Group.HasValue()); + EXPECT_EQ( + createSymbolicLinkResult.PosixProperties.Group.Value(), + createSymbolicLinkOptions.Group.Value()); + EXPECT_TRUE(createSymbolicLinkResult.PosixProperties.FileMode.HasValue()); + EXPECT_EQ( + createSymbolicLinkResult.PosixProperties.Owner.Value(), + createSymbolicLinkOptions.Owner.Value()); + EXPECT_TRUE(createSymbolicLinkResult.PosixProperties.NfsFileType.HasValue()); + EXPECT_EQ( + createSymbolicLinkResult.PosixProperties.NfsFileType.Value(), + Files::Shares::Models::NfsFileType::SymLink); + EXPECT_EQ( + createSymbolicLinkResult.SmbProperties.CreatedOn.Value(), + createSymbolicLinkOptions.CreatedOn.Value()); + EXPECT_EQ( + createSymbolicLinkResult.SmbProperties.LastWrittenOn.Value(), + createSymbolicLinkOptions.LastWrittenOn.Value()); + EXPECT_TRUE(createSymbolicLinkResult.SmbProperties.ChangedOn.HasValue()); + EXPECT_TRUE(!createSymbolicLinkResult.SmbProperties.FileId.empty()); + EXPECT_TRUE(!createSymbolicLinkResult.SmbProperties.ParentFileId.empty()); + EXPECT_TRUE(createSymbolicLinkResult.ETag.HasValue()); + + // Get SymbolicLink + Files::Shares::Models::GetFileSymbolicLinkResult getSymbolicLinkResult; + EXPECT_NO_THROW(getSymbolicLinkResult = symbolicLinkClient.GetSymbolicLink().Value); + EXPECT_TRUE(getSymbolicLinkResult.ETag.HasValue()); + if (!m_testContext.IsPlaybackMode()) + { + EXPECT_EQ(Azure::Core::Url::Decode(getSymbolicLinkResult.LinkText), sourceUrl); + } + // Create HardLink auto hardLinkClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString()); @@ -2417,7 +2467,7 @@ namespace Azure { namespace Storage { namespace Test { Files::Shares::Models::NfsFileType::Regular); } - TEST_F(FileShareFileClientTest, PremiumNfsPropertiesForCopy_PLAYBACKONLY_) + TEST_F(FileShareFileClientTest, PremiumPosixPropertiesForCopy_PLAYBACKONLY_) { auto shareServiceClient = *m_premiumShareServiceClient; @@ -2509,7 +2559,7 @@ namespace Azure { namespace Storage { namespace Test { EXPECT_EQ( properties.PosixProperties.Owner.Value(), createOptions.PosixProperties.Owner.Value()); - // Copy without NfsProperties + // Copy without PosixProperties copyOptions = Files::Shares::StartFileCopyOptions(); copyOptions.SmbPropertiesToCopy = Files::Shares::CopyableFileSmbPropertyFlags::None; destFileClient = shareClient.GetRootDirectoryClient().GetFileClient(LowercaseRandomString()); diff --git a/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp b/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp index 74ba66f1a..1b4a338da 100644 --- a/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp +++ b/sdk/storage/azure-storage-queues/test/ut/queue_client_test.cpp @@ -235,6 +235,18 @@ namespace Azure { namespace Storage { namespace Test { queueClient.Delete(); } + TEST_F(QueueClientTest, AclOAuth_PLAYBACKONLY_) + { + auto credential = GetTestCredential(); + auto clientOptions = InitStorageClientOptions(); + auto queueClient = Queues::QueueClient(m_queueClient->GetUrl(), credential, clientOptions); + + Queues::Models::QueueAccessPolicy accessPolicy; + EXPECT_NO_THROW(queueClient.SetAccessPolicy(accessPolicy)); + + EXPECT_NO_THROW(queueClient.GetAccessPolicy()); + } + TEST_F(QueueClientTest, Audience) { auto credential = GetTestCredential();